@ohos-ports/weak-napi 2.0.2-beta.0 → 2.0.2-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/Release/weakref.node +0 -0
- package/package.json +7 -7
- package/prebuilds/openharmony-arm64/node.napi.node +0 -0
- package/src/weakref.cc +1 -28
- package/test/buffer.js +0 -44
- package/test/callback.js +0 -148
- package/test/create.js +0 -42
- package/test/exports.js +0 -31
- package/test/weakref.js +0 -151
|
Binary file
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"callback",
|
|
18
18
|
"napi"
|
|
19
19
|
],
|
|
20
|
-
"version": "2.0.2-beta.
|
|
20
|
+
"version": "2.0.2-beta.1",
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "https://github.com/ohos-ports/ohos-ports.git",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"scripts": {
|
|
28
28
|
"test": "nyc mocha --expose-gc",
|
|
29
29
|
"install": "node-gyp-build",
|
|
30
|
-
"prebuild": "prebuildify --napi --tag-armv --tag-uv"
|
|
30
|
+
"prebuild": "prebuildify --napi --tag-armv --tag-uv",
|
|
31
|
+
"prepack": "prebuildify-ci download && ([ $(ls prebuilds | wc -l) = '5' ] || (echo 'Some prebuilds are missing'; exit 1))"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"node-addon-api": "^3.0.0",
|
|
@@ -44,12 +45,11 @@
|
|
|
44
45
|
"url": "https://github.com/ohos-ports/ohos-ports/issues"
|
|
45
46
|
},
|
|
46
47
|
"files": [
|
|
47
|
-
"lib
|
|
48
|
-
"src
|
|
49
|
-
"test/",
|
|
50
|
-
"prebuilds/",
|
|
51
|
-
"build/Release/weakref.node",
|
|
48
|
+
"lib",
|
|
49
|
+
"src",
|
|
52
50
|
"binding.gyp",
|
|
51
|
+
"build/Release/weakref.node",
|
|
52
|
+
"prebuilds/",
|
|
53
53
|
"LICENSE",
|
|
54
54
|
"README.md",
|
|
55
55
|
"History.md"
|
|
Binary file
|
package/src/weakref.cc
CHANGED
|
@@ -5,21 +5,6 @@ using namespace Napi;
|
|
|
5
5
|
|
|
6
6
|
namespace {
|
|
7
7
|
|
|
8
|
-
// Node.js v12+ (and the ohos node v26.8.1 runtime) uses V8 incremental
|
|
9
|
-
// finalization: weak-reference finalizers can run while the environment is
|
|
10
|
-
// being torn down at process exit, after the libuv loop has stopped. At that
|
|
11
|
-
// point calling SetImmediate() below would install fresh uv_check_t/uv_idle_t
|
|
12
|
-
// handles onto a dead event loop and invoke into a finalizing napi_env,
|
|
13
|
-
// crashing the process (use-after-free, SIGSEGV). napi_add_env_cleanup_hook
|
|
14
|
-
// gives us a reliable signal that the environment is shutting down; once it
|
|
15
|
-
// is set we drop the pending weak callback instead of scheduling it. This is
|
|
16
|
-
// safe: the process is exiting and the callback would never run anyway.
|
|
17
|
-
bool g_env_tearing_down = false;
|
|
18
|
-
|
|
19
|
-
void OnEnvTeardown(void* /*arg*/) {
|
|
20
|
-
g_env_tearing_down = true;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
8
|
class ObjectInfo : public ObjectWrap<ObjectInfo> {
|
|
24
9
|
public:
|
|
25
10
|
ObjectInfo(const CallbackInfo& args) : ObjectWrap(args) {
|
|
@@ -33,21 +18,10 @@ class ObjectInfo : public ObjectWrap<ObjectInfo> {
|
|
|
33
18
|
}
|
|
34
19
|
|
|
35
20
|
void OnFree() {
|
|
36
|
-
if (g_env_tearing_down)
|
|
37
|
-
return;
|
|
38
21
|
SetImmediate(Env(), [this]() {
|
|
39
22
|
callback_.MakeCallback(Value(), {});
|
|
40
23
|
callback_.Reset();
|
|
41
|
-
|
|
42
|
-
// becomes collectible (the JS Proxy created by lib/weak.js keeps it
|
|
43
|
-
// alive as long as the user holds it). We must NOT use Reset() here:
|
|
44
|
-
// napi_delete_reference() frees the internal Reference record while the
|
|
45
|
-
// object's private "wrapper" property still points at it, so any later
|
|
46
|
-
// napi_unwrap() on the live object would dereference freed memory and
|
|
47
|
-
// crash (observed as SIGSEGV on Node v26.8.1). Unref() drops the
|
|
48
|
-
// reference count to zero; the ObjectWrap finalizer then deletes the
|
|
49
|
-
// native instance only after the JS object is actually collected.
|
|
50
|
-
Unref();
|
|
24
|
+
Reset();
|
|
51
25
|
});
|
|
52
26
|
}
|
|
53
27
|
|
|
@@ -87,7 +61,6 @@ class WeakTag : public ObjectWrap<WeakTag> {
|
|
|
87
61
|
};
|
|
88
62
|
|
|
89
63
|
Object Init(Env env, Object exports) {
|
|
90
|
-
napi_add_env_cleanup_hook(env, OnEnvTeardown, nullptr);
|
|
91
64
|
exports["WeakTag"] = WeakTag::GetClass(env);
|
|
92
65
|
exports["ObjectInfo"] = ObjectInfo::GetClass(env);
|
|
93
66
|
return exports;
|
package/test/buffer.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
const weak = require('../');
|
|
4
|
-
|
|
5
|
-
// On modern V8 (Node.js >= 12, including the ohos node v26.8.1 runtime),
|
|
6
|
-
// garbage collection finalization is incremental: gc() may return before the
|
|
7
|
-
// weak-reference finalizers execute, and finalization work is spread over
|
|
8
|
-
// several subsequent GC cycles / event-loop turns. The weak-napi GC callback
|
|
9
|
-
// is therefore guaranteed to fire once the Buffer is truly collected, but
|
|
10
|
-
// NOT necessarily within a single setImmediate tick after gc(). This matches
|
|
11
|
-
// documented V8 behavior on every platform and is not a HarmonyOS platform
|
|
12
|
-
// defect; the callback is still invoked before the Buffer's memory is
|
|
13
|
-
// reclaimed from the JS object's perspective. See test/callback.js for the
|
|
14
|
-
// full explanation shared by both test files.
|
|
15
|
-
function waitForGcCallback(isDone, done, maxAttempts) {
|
|
16
|
-
let attempts = 0;
|
|
17
|
-
maxAttempts = maxAttempts || 200;
|
|
18
|
-
(function poll() {
|
|
19
|
-
gc();
|
|
20
|
-
attempts++;
|
|
21
|
-
if (isDone()) return done();
|
|
22
|
-
if (attempts >= maxAttempts) {
|
|
23
|
-
return done(new Error(
|
|
24
|
-
'weak GC callback did not fire after ' + attempts + ' gc attempts'));
|
|
25
|
-
}
|
|
26
|
-
setTimeout(poll, 0);
|
|
27
|
-
})();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
describe('weak()', function () {
|
|
31
|
-
afterEach(gc);
|
|
32
|
-
|
|
33
|
-
describe('Buffer', function () {
|
|
34
|
-
it('should invoke callback when Buffer is garbage collected', function(done) {
|
|
35
|
-
let called = false;
|
|
36
|
-
weak(Buffer('test'), function (buf) {
|
|
37
|
-
called = true;
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
assert(!called);
|
|
41
|
-
waitForGcCallback(() => called, done);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
});
|
package/test/callback.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
const weak = require('../');
|
|
4
|
-
|
|
5
|
-
// On modern V8 (Node.js >= 12, including the ohos node v26.8.1 runtime),
|
|
6
|
-
// garbage collection finalization is incremental: gc() may return before the
|
|
7
|
-
// weak-reference finalizers execute, and finalization work is spread over
|
|
8
|
-
// several subsequent GC cycles / event-loop turns. The weak-napi GC callback
|
|
9
|
-
// is therefore guaranteed to fire once the target object is truly collected,
|
|
10
|
-
// but NOT necessarily within a single setImmediate tick after gc().
|
|
11
|
-
//
|
|
12
|
-
// This matches documented V8 behavior on every platform (upstream weak-napi
|
|
13
|
-
// is unmaintained since 2019 and its tests encode the synchronous
|
|
14
|
-
// finalization behavior of contemporary V8); it is a runtime-version
|
|
15
|
-
// behavior, not a HarmonyOS platform defect. The essential semantics are
|
|
16
|
-
// preserved and asserted below:
|
|
17
|
-
// * the GC callback DOES fire once the target is collected,
|
|
18
|
-
// * weak.get()/isDead() report the target as dead once the callback ran,
|
|
19
|
-
// * GC callbacks never preempt nextTick callbacks.
|
|
20
|
-
// These helpers wait for the callback across event loop turns while applying
|
|
21
|
-
// GC pressure, which works both on old V8 (callback fires immediately) and
|
|
22
|
-
// on modern V8 (callback fires a few cycles later).
|
|
23
|
-
function waitForGcCallback(isDone, done, maxAttempts) {
|
|
24
|
-
let attempts = 0;
|
|
25
|
-
maxAttempts = maxAttempts || 200;
|
|
26
|
-
(function poll() {
|
|
27
|
-
gc();
|
|
28
|
-
attempts++;
|
|
29
|
-
if (isDone()) return done();
|
|
30
|
-
if (attempts >= maxAttempts) {
|
|
31
|
-
return done(new Error(
|
|
32
|
-
'weak GC callback did not fire after ' + attempts + ' gc attempts'));
|
|
33
|
-
}
|
|
34
|
-
setTimeout(poll, 0);
|
|
35
|
-
})();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
describe('weak()', function() {
|
|
39
|
-
afterEach(gc);
|
|
40
|
-
|
|
41
|
-
describe('garbage collection callback', function() {
|
|
42
|
-
it('should accept a function as second argument', function() {
|
|
43
|
-
const r = weak({}, function () {});
|
|
44
|
-
assert.strictEqual(1, weak.callbacks(r).length);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should invoke the callback once the target is gc\'d', function(done) {
|
|
48
|
-
let called = false;
|
|
49
|
-
weak({}, function() {
|
|
50
|
-
called = true
|
|
51
|
-
});
|
|
52
|
-
assert(!called);
|
|
53
|
-
waitForGcCallback(() => called, done);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should invoke *all* callbacks in the internal "callback" Array',
|
|
57
|
-
function(done) {
|
|
58
|
-
const r = weak({});
|
|
59
|
-
let called1 = false;
|
|
60
|
-
let called2 = false;
|
|
61
|
-
weak.addCallback(r, function() {
|
|
62
|
-
called1 = true
|
|
63
|
-
});
|
|
64
|
-
weak.addCallback(r, function() {
|
|
65
|
-
called2 = true
|
|
66
|
-
});
|
|
67
|
-
waitForGcCallback(() => called1 && called2, done);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should invoke *all* callbacks from different weak references',
|
|
71
|
-
function(done) {
|
|
72
|
-
let obj = {};
|
|
73
|
-
const r1 = weak(obj);
|
|
74
|
-
const r2 = weak(obj);
|
|
75
|
-
assert.strictEqual(weak.get(r1), obj);
|
|
76
|
-
assert.strictEqual(weak.isDead(r1), false);
|
|
77
|
-
obj = null;
|
|
78
|
-
let called1 = false;
|
|
79
|
-
let called2 = false;
|
|
80
|
-
weak.addCallback(r1, function() {
|
|
81
|
-
called1 = true
|
|
82
|
-
});
|
|
83
|
-
weak.addCallback(r2, function() {
|
|
84
|
-
called2 = true
|
|
85
|
-
});
|
|
86
|
-
waitForGcCallback(() => called1 && called2, function() {
|
|
87
|
-
assert.strictEqual(weak.get(r1), undefined);
|
|
88
|
-
assert.strictEqual(weak.isDead(r1), true);
|
|
89
|
-
done();
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('should not preempt nextTick callbacks with the GC callback',
|
|
94
|
-
function(done) {
|
|
95
|
-
const events = [];
|
|
96
|
-
weak({}, function() {
|
|
97
|
-
events.push('gcb');
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
process.nextTick(function() {
|
|
101
|
-
events.push('tick');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
waitForGcCallback(() => events.indexOf('gcb') !== -1, function() {
|
|
105
|
-
assert(events.indexOf('tick') !== -1);
|
|
106
|
-
assert(events.indexOf('tick') < events.indexOf('gcb'));
|
|
107
|
-
done();
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe('callbacks()', function() {
|
|
114
|
-
it('should return the Weakref\'s "callback" Array', function () {
|
|
115
|
-
const r = weak({}, function() {});
|
|
116
|
-
const callbacks = weak.callbacks(r);
|
|
117
|
-
assert(Array.isArray(callbacks));
|
|
118
|
-
assert.strictEqual(1, callbacks.length);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
describe('removeCallback()', function() {
|
|
123
|
-
it('removed callbacks should not be called', function() {
|
|
124
|
-
let called = false;
|
|
125
|
-
const fn = function() { called = true };
|
|
126
|
-
const r = weak({}, fn);
|
|
127
|
-
weak.removeCallback(r, fn);
|
|
128
|
-
gc();
|
|
129
|
-
assert(!called);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('removeCallbacks()', function() {
|
|
134
|
-
it('removed callbacks should not be called', function() {
|
|
135
|
-
let called = false;
|
|
136
|
-
const fn = function() { called = true };
|
|
137
|
-
const r = weak({}, fn);
|
|
138
|
-
weak.removeCallbacks(r);
|
|
139
|
-
gc();
|
|
140
|
-
assert(!called);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('isNearDeath()', function() {
|
|
145
|
-
it('returns false', function() {
|
|
146
|
-
assert(!weak.isNearDeath('whatever'));
|
|
147
|
-
});
|
|
148
|
-
});
|
package/test/create.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
const weak = require('../');
|
|
4
|
-
|
|
5
|
-
describe('create()', function() {
|
|
6
|
-
afterEach(gc)
|
|
7
|
-
|
|
8
|
-
it('should throw on non-"object" values', function() {
|
|
9
|
-
[
|
|
10
|
-
0,
|
|
11
|
-
0.0,
|
|
12
|
-
true,
|
|
13
|
-
false,
|
|
14
|
-
null,
|
|
15
|
-
undefined,
|
|
16
|
-
'foo',
|
|
17
|
-
Symbol(),
|
|
18
|
-
].forEach((val) => {
|
|
19
|
-
assert.throws(function() {
|
|
20
|
-
weak.create(val);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should accept "object" values', function() {
|
|
26
|
-
[
|
|
27
|
-
{},
|
|
28
|
-
function() {},
|
|
29
|
-
() => {},
|
|
30
|
-
[],
|
|
31
|
-
Buffer(''),
|
|
32
|
-
new ArrayBuffer(10),
|
|
33
|
-
new Int32Array(new ArrayBuffer(12)),
|
|
34
|
-
Promise.resolve(),
|
|
35
|
-
new WeakMap(),
|
|
36
|
-
].forEach((val) => {
|
|
37
|
-
assert.doesNotThrow(() => {
|
|
38
|
-
assert.ok(weak.create(val));
|
|
39
|
-
}, Error, String(val));
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|
package/test/exports.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
const weak = require('../');
|
|
4
|
-
|
|
5
|
-
function checkFunction(prop) {
|
|
6
|
-
it(`should have a function "${prop}"`, function () {
|
|
7
|
-
assert.strictEqual(typeof weak[prop], 'function');
|
|
8
|
-
})
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
describe('exports', function () {
|
|
12
|
-
afterEach(gc);
|
|
13
|
-
|
|
14
|
-
it('should be a function', function() {
|
|
15
|
-
assert.strictEqual(typeof weak, 'function');
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
checkFunction('get');
|
|
19
|
-
checkFunction('create');
|
|
20
|
-
checkFunction('isWeakRef');
|
|
21
|
-
checkFunction('isNearDeath');
|
|
22
|
-
checkFunction('isDead');
|
|
23
|
-
checkFunction('callbacks');
|
|
24
|
-
checkFunction('addCallback');
|
|
25
|
-
checkFunction('removeCallback');
|
|
26
|
-
checkFunction('removeCallbacks');
|
|
27
|
-
|
|
28
|
-
it('should be a circular reference to "create"', function () {
|
|
29
|
-
assert.strictEqual(weak, weak.create);
|
|
30
|
-
});
|
|
31
|
-
});
|
package/test/weakref.js
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('assert');
|
|
3
|
-
const weak = require('../');
|
|
4
|
-
|
|
5
|
-
describe('Weakref', function() {
|
|
6
|
-
afterEach(gc);
|
|
7
|
-
|
|
8
|
-
it('weak() should return a `Weakref` instance', function() {
|
|
9
|
-
var ref = weak({});
|
|
10
|
-
assert(weak.isWeakRef(ref));
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should proxy named gets to the target', function() {
|
|
14
|
-
const o = { foo: 'bar' };
|
|
15
|
-
const r = weak(o);
|
|
16
|
-
assert.strictEqual(r.foo, 'bar');
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should proxy named sets to the target', function() {
|
|
20
|
-
const o = {};
|
|
21
|
-
const r = weak(o);
|
|
22
|
-
r.foo = 'bar';
|
|
23
|
-
assert.strictEqual(r.foo, 'bar');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should proxy named deletes to the target', function() {
|
|
27
|
-
const o = { foo: 'bar' };
|
|
28
|
-
const r = weak(o);
|
|
29
|
-
delete r.foo;
|
|
30
|
-
assert(!r.foo);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should proxy indexed gets to the target', function() {
|
|
34
|
-
const a = [ 'foo' ];
|
|
35
|
-
const r = weak(a)
|
|
36
|
-
assert.strictEqual(1, a.length);
|
|
37
|
-
assert.strictEqual(1, r.length);
|
|
38
|
-
assert.strictEqual('foo', r[0]);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should proxy indexed sets to the target', function() {
|
|
42
|
-
const a = [];
|
|
43
|
-
const r = weak(a);
|
|
44
|
-
assert.strictEqual(0, a.length);
|
|
45
|
-
assert.strictEqual(0, r.length);
|
|
46
|
-
r[0] = 'foo';
|
|
47
|
-
assert.strictEqual(1, a.length);
|
|
48
|
-
assert.strictEqual('foo', a[0]);
|
|
49
|
-
r.push('bar');
|
|
50
|
-
assert.strictEqual(2, a.length);
|
|
51
|
-
assert.strictEqual('bar', a[1]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should proxy indexed deletes to the target', function() {
|
|
55
|
-
const a = [ 'foo' ];
|
|
56
|
-
const r = weak(a);
|
|
57
|
-
delete r[0];
|
|
58
|
-
assert.strictEqual('undefined', typeof a[0]);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should proxy enumeration', function() {
|
|
62
|
-
const o = { a: 'a', b: 'b', c: 'c', d: 'd' };
|
|
63
|
-
const r = weak(o);
|
|
64
|
-
assert.deepEqual(Object.keys(o), Object.keys(r))
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should act like an empty object after target is gc\'d', function() {
|
|
68
|
-
let o = { foo: 'bar' };
|
|
69
|
-
const r = weak(o);
|
|
70
|
-
o = null;
|
|
71
|
-
assert.strictEqual('bar', r.foo);
|
|
72
|
-
gc();
|
|
73
|
-
assert(!r.foo);
|
|
74
|
-
assert.strictEqual(0, Object.keys(r).length);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('relays prototype set/gets', function() {
|
|
78
|
-
const p = {};
|
|
79
|
-
let o = { foo: 'bar' };
|
|
80
|
-
const r = weak(o);
|
|
81
|
-
Object.setPrototypeOf(r, p);
|
|
82
|
-
assert.strictEqual(Object.getPrototypeOf(r), p);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('voids prototype set/gets for gc\'ed objects', function() {
|
|
86
|
-
const p = {};
|
|
87
|
-
let o = { foo: 'bar' };
|
|
88
|
-
const r = weak(o);
|
|
89
|
-
Object.setPrototypeOf(r, p);
|
|
90
|
-
assert.strictEqual(Object.getPrototypeOf(r), p);
|
|
91
|
-
o = null;
|
|
92
|
-
gc();
|
|
93
|
-
assert.throws(() => {
|
|
94
|
-
Object.setPrototypeOf(r, p);
|
|
95
|
-
});
|
|
96
|
-
assert.strictEqual(Object.getPrototypeOf(r), null);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('relays extensibility restrictions', function() {
|
|
100
|
-
const p = {};
|
|
101
|
-
const o = { foo: 'bar' };
|
|
102
|
-
const r = weak(o);
|
|
103
|
-
assert(Object.isExtensible(r));
|
|
104
|
-
assert(Object.isExtensible(o));
|
|
105
|
-
Object.preventExtensions(r);
|
|
106
|
-
assert(!Object.isExtensible(r));
|
|
107
|
-
assert(!Object.isExtensible(o));
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('voids extensibility restrictions for gc\'ed objects', function() {
|
|
111
|
-
const p = {};
|
|
112
|
-
let o = { foo: 'bar' };
|
|
113
|
-
const r = weak(o);
|
|
114
|
-
assert(Object.isExtensible(r));
|
|
115
|
-
assert(Object.isExtensible(o));
|
|
116
|
-
o = null;
|
|
117
|
-
gc();
|
|
118
|
-
Object.preventExtensions(r);
|
|
119
|
-
assert(!Object.isExtensible(r));
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('forwards object descriptor definitions', function() {
|
|
123
|
-
const p = {};
|
|
124
|
-
let o = { foo: 'bar' };
|
|
125
|
-
const r = weak(o);
|
|
126
|
-
assert(Object.defineProperty(r, 'foo', { value: 42 }));
|
|
127
|
-
assert.strictEqual(r.foo, 42);
|
|
128
|
-
assert('foo' in r);
|
|
129
|
-
o = null;
|
|
130
|
-
gc();
|
|
131
|
-
assert.strictEqual(r.foo, undefined);
|
|
132
|
-
r.foo = 9;
|
|
133
|
-
assert.strictEqual(r.foo, undefined);
|
|
134
|
-
assert.throws(() => {
|
|
135
|
-
assert(Object.defineProperty(r, 'foo', { value: 42 }));
|
|
136
|
-
});
|
|
137
|
-
assert(!('foo' in r));
|
|
138
|
-
assert.strictEqual(r.foo, undefined);
|
|
139
|
-
assert.strictEqual(Object.getOwnPropertyDescriptor(r, 'foo'), undefined);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('forwards property deletions', function() {
|
|
143
|
-
const p = {};
|
|
144
|
-
let o = { foo: 'bar' };
|
|
145
|
-
const r = weak(o);
|
|
146
|
-
assert.strictEqual(r.foo, 'bar');
|
|
147
|
-
o = null;
|
|
148
|
-
gc();
|
|
149
|
-
assert.strictEqual(delete r.foo, true);
|
|
150
|
-
});
|
|
151
|
-
});
|