/
callback.js
133 lines (120 loc) · 3.28 KB
/
callback.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
'use strict';
const assert = require('assert');
const weak = require('../');
const tick = (n, cb) => n === 0 ? cb() : setImmediate(tick, n-1, cb);
describe('weak()', function() {
afterEach(gc);
describe('garbage collection callback', function() {
it('should accept a function as second argument', function() {
const r = weak({}, function () {});
assert.strictEqual(1, weak.callbacks(r).length);
});
it('should invoke the callback before the target is gc\'d', function(done) {
let called = false;
weak({}, function() {
called = true
});
assert(!called);
gc();
tick(3, () => {
assert(called);
done();
});
});
it('should invoke *all* callbacks in the internal "callback" Array',
function(done) {
const r = weak({});
let called1 = false;
let called2 = false;
weak.addCallback(r, function() {
called1 = true
});
weak.addCallback(r, function() {
called2 = true
});
gc();
tick(3, () => {
assert(called1);
assert(called2);
done();
});
});
it('should invoke *all* callbacks from different weak references',
function(done) {
let obj = {};
const r1 = weak(obj);
const r2 = weak(obj);
assert.strictEqual(weak.get(r1), obj);
assert.strictEqual(weak.isDead(r1), false);
obj = null;
let called1 = false;
let called2 = false;
weak.addCallback(r1, function() {
called1 = true
});
weak.addCallback(r2, function() {
called2 = true
});
gc();
tick(3, () => {
assert.strictEqual(weak.get(r1), undefined);
assert.strictEqual(weak.isDead(r1), true);
assert(called1);
assert(called2);
done();
});
});
it('should preempt code for GC callback but not nextTick callbacks',
function(done) {
let calledGcCallback = false;
let calledTickCallback = false;
weak({}, function() {
calledGcCallback = true
});
process.nextTick(function() {
calledTickCallback = true
});
assert(!calledGcCallback);
assert(!calledTickCallback);
gc();
tick(3, () => {
assert(calledGcCallback);
assert(calledTickCallback);
done();
});
});
});
});
describe('callbacks()', function() {
it('should return the Weakref\'s "callback" Array', function () {
const r = weak({}, function() {});
const callbacks = weak.callbacks(r);
assert(Array.isArray(callbacks));
assert.strictEqual(1, callbacks.length);
});
});
describe('removeCallback()', function() {
it('removed callbacks should not be called', function() {
let called = false;
const fn = function() { called = true };
const r = weak({}, fn);
weak.removeCallback(r, fn);
gc();
assert(!called);
});
});
describe('removeCallbacks()', function() {
it('removed callbacks should not be called', function() {
let called = false;
const fn = function() { called = true };
const r = weak({}, fn);
weak.removeCallbacks(r);
gc();
assert(!called);
});
});
describe('isNearDeath()', function() {
it('returns false', function() {
assert(!weak.isNearDeath('whatever'));
});
});