forked from meteor/meteor
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfiber-helpers.js
More file actions
135 lines (113 loc) · 3.46 KB
/
fiber-helpers.js
File metadata and controls
135 lines (113 loc) · 3.46 KB
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
134
135
var _ = require("underscore");
var Fiber = require("fibers");
exports.parallelEach = function (collection, callback, context) {
const errors = [];
context = context || null;
const results = Promise.all(_.map(collection, (...args) => {
async function run() {
return callback.apply(context, args);
}
return run().catch(error => {
// Collect the errors but do not propagate them so that we can
// re-throw the first error after all iterations have completed.
errors.push(error);
});
})).await();
if (errors.length > 0) {
throw errors[0];
}
return results;
};
function disallowedYield() {
throw new Error("Can't call yield in a noYieldsAllowed block!");
}
// Allow testing Fiber.yield.disallowed.
disallowedYield.disallowed = true;
exports.noYieldsAllowed = function (f, context) {
var savedYield = Fiber.yield;
Fiber.yield = disallowedYield;
try {
return f.call(context || null);
} finally {
Fiber.yield = savedYield;
}
};
// Borrowed from packages/meteor/dynamics_nodejs.js
// Used by buildmessage
exports.nodeCodeMustBeInFiber = function () {
if (!Fiber.current) {
throw new Error("Meteor code must always run within a Fiber. " +
"Try wrapping callbacks that you pass to non-Meteor " +
"libraries with Meteor.bindEnvironment.");
}
};
var nextSlot = 0;
exports.EnvironmentVariable = function (defaultValue) {
var self = this;
self.slot = 'slot' + nextSlot++;
self.defaultValue = defaultValue;
};
_.extend(exports.EnvironmentVariable.prototype, {
get: function () {
var self = this;
exports.nodeCodeMustBeInFiber();
if (!Fiber.current._meteorDynamics) {
return self.defaultValue;
}
if (!_.has(Fiber.current._meteorDynamics, self.slot)) {
return self.defaultValue;
}
return Fiber.current._meteorDynamics[self.slot];
},
withValue: function (value, func) {
var self = this;
exports.nodeCodeMustBeInFiber();
if (!Fiber.current._meteorDynamics) {
Fiber.current._meteorDynamics = {};
}
var currentValues = Fiber.current._meteorDynamics;
var saved = _.has(currentValues, self.slot)
? currentValues[self.slot] : self.defaultValue;
currentValues[self.slot] = value;
try {
return func();
} finally {
currentValues[self.slot] = saved;
}
}
});
// This is like Meteor.bindEnvironment.
// Experimentally, we are NOT including onException or _this in this version.
exports.bindEnvironment = function (func) {
exports.nodeCodeMustBeInFiber();
var boundValues = _.clone(Fiber.current._meteorDynamics || {});
return function (...args) {
var self = this;
var runWithEnvironment = function () {
var savedValues = Fiber.current._meteorDynamics;
try {
// Need to clone boundValues in case two fibers invoke this
// function at the same time
Fiber.current._meteorDynamics = _.clone(boundValues);
return func.apply(self, args);
} finally {
Fiber.current._meteorDynamics = savedValues;
}
};
if (Fiber.current) {
return runWithEnvironment();
}
Fiber(runWithEnvironment).run();
};
};
// Returns a Promise that supports .resolve(result) and .reject(error).
exports.makeFulfillablePromise = function () {
var resolve, reject;
var promise = new Promise(function (res, rej) {
resolve = res;
reject = rej;
});
promise.resolve = resolve;
promise.reject = reject;
return promise;
};