q5 2.9.21 → 2.9.23
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/.vscode/launch.json +26 -0
- package/bun.lockb +0 -0
- package/p5-tests/js/chai_helpers.js +20 -0
- package/p5-tests/js/mocha_setup.js +2 -0
- package/p5-tests/js/modernizr.js +5 -0
- package/p5-tests/js/p5_helpers.js +135 -0
- package/p5-tests/js/sinon.js +5949 -0
- package/p5-tests/mocha.css +289 -0
- package/p5-tests/test.html +71 -0
- package/p5-tests/unit/color/color_conversion.js +68 -0
- package/p5-tests/unit/color/creating_reading.js +217 -0
- package/p5-tests/unit/color/p5.Color.js +1000 -0
- package/p5-tests/unit/color/setting.js +289 -0
- package/p5-tests/unit/core/2d_primitives.js +490 -0
- package/p5-tests/unit/core/attributes.js +115 -0
- package/p5-tests/unit/core/curves.js +139 -0
- package/p5-tests/unit/core/environment.js +248 -0
- package/p5-tests/unit/core/error_helpers.js +1158 -0
- package/p5-tests/unit/core/main.js +340 -0
- package/p5-tests/unit/core/p5.Element.js +773 -0
- package/p5-tests/unit/core/p5.Graphics.js +179 -0
- package/p5-tests/unit/core/preload.js +285 -0
- package/p5-tests/unit/core/rendering.js +116 -0
- package/p5-tests/unit/core/structure.js +293 -0
- package/p5-tests/unit/core/transform.js +144 -0
- package/p5-tests/unit/core/version.js +28 -0
- package/p5-tests/unit/core/vertex.js +137 -0
- package/p5-tests/unit/dom/dom.js +2146 -0
- package/p5-tests/unit/events/acceleration.js +213 -0
- package/p5-tests/unit/events/keyboard.js +179 -0
- package/p5-tests/unit/events/mouse.js +487 -0
- package/p5-tests/unit/events/touch.js +180 -0
- package/p5-tests/unit/image/downloading.js +379 -0
- package/p5-tests/unit/image/filters.js +92 -0
- package/p5-tests/unit/image/loading.js +413 -0
- package/p5-tests/unit/image/p5.Image.js +201 -0
- package/p5-tests/unit/image/pixels.js +234 -0
- package/p5-tests/unit/io/files.js +378 -0
- package/p5-tests/unit/io/loadBytes.js +149 -0
- package/p5-tests/unit/io/loadImage.js +123 -0
- package/p5-tests/unit/io/loadJSON.js +185 -0
- package/p5-tests/unit/io/loadModel.js +215 -0
- package/p5-tests/unit/io/loadShader.js +176 -0
- package/p5-tests/unit/io/loadStrings.js +140 -0
- package/p5-tests/unit/io/loadTable.js +183 -0
- package/p5-tests/unit/io/loadXML.js +127 -0
- package/p5-tests/unit/io/saveModel.js +113 -0
- package/p5-tests/unit/io/saveTable.js +142 -0
- package/p5-tests/unit/math/calculation.js +452 -0
- package/p5-tests/unit/math/noise.js +66 -0
- package/p5-tests/unit/math/p5.Vector.js +1886 -0
- package/p5-tests/unit/math/random.js +177 -0
- package/p5-tests/unit/math/trigonometry.js +144 -0
- package/p5-tests/unit/spec.js +50 -0
- package/p5-tests/unit/typography/attributes.js +120 -0
- package/p5-tests/unit/typography/loadFont.js +162 -0
- package/p5-tests/unit/typography/p5.Font.js +63 -0
- package/p5-tests/unit/utilities/conversion.js +329 -0
- package/p5-tests/unit/utilities/time_date.js +133 -0
- package/package.json +1 -1
- package/q5.js +158 -54
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +8 -2
- package/src/q5-2d-drawing.js +20 -7
- package/src/q5-2d-image.js +4 -1
- package/src/q5-2d-text.js +7 -0
- package/src/q5-canvas.js +6 -5
- package/src/q5-color.js +5 -0
- package/src/q5-core.js +3 -1
- package/src/q5-input.js +12 -0
- package/src/q5-math.js +11 -3
- package/src/q5-record.js +2 -0
- package/src/q5-vector.js +33 -0
- package/src/q5-webgpu-canvas.js +11 -7
- package/src/q5-webgpu-drawing.js +15 -12
- package/src/q5-webgpu-image.js +1 -1
- package/src/q5-webgpu-text.js +22 -15
|
@@ -0,0 +1,1158 @@
|
|
|
1
|
+
suite('Error Helpers', function() {
|
|
2
|
+
var myp5;
|
|
3
|
+
|
|
4
|
+
setup(function(done) {
|
|
5
|
+
new p5(function(p) {
|
|
6
|
+
p.setup = function() {
|
|
7
|
+
myp5 = p;
|
|
8
|
+
p5._clearValidateParamsCache();
|
|
9
|
+
done();
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
teardown(function() {
|
|
15
|
+
myp5.remove();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
suite('friendly error logger', function() {
|
|
19
|
+
test('basic', function() {
|
|
20
|
+
assert.doesNotThrow(
|
|
21
|
+
function() {
|
|
22
|
+
p5._friendlyError('basic', 'basic');
|
|
23
|
+
},
|
|
24
|
+
Error,
|
|
25
|
+
'got unwanted exception'
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// unit tests for validateParameters
|
|
31
|
+
suite('validateParameters: Numbers + optional Constant', function() {
|
|
32
|
+
test('arc(): no friendly-err-msg', function() {
|
|
33
|
+
assert.doesNotThrow(
|
|
34
|
+
function() {
|
|
35
|
+
p5._validateParameters('arc', [1, 1, 10.5, 10, 0, Math.PI, 'pie']);
|
|
36
|
+
},
|
|
37
|
+
Error,
|
|
38
|
+
'got unwanted exception'
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
test('arc(): missing param #4, #5', function() {
|
|
42
|
+
assert.validationError(function() {
|
|
43
|
+
p5._validateParameters('arc', [1, 1, 10.5, 10]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
test('arc(): missing param #0', function() {
|
|
47
|
+
assert.validationError(function() {
|
|
48
|
+
p5._validateParameters('arc', [
|
|
49
|
+
undefined,
|
|
50
|
+
1,
|
|
51
|
+
10.5,
|
|
52
|
+
10,
|
|
53
|
+
0,
|
|
54
|
+
Math.PI,
|
|
55
|
+
'pie'
|
|
56
|
+
]);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
test('arc(): missing param #4', function() {
|
|
60
|
+
assert.validationError(function() {
|
|
61
|
+
p5._validateParameters('arc', [
|
|
62
|
+
1,
|
|
63
|
+
1,
|
|
64
|
+
10.5,
|
|
65
|
+
10,
|
|
66
|
+
undefined,
|
|
67
|
+
Math.PI,
|
|
68
|
+
'pie'
|
|
69
|
+
]);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
test('arc(): missing param #5', function() {
|
|
73
|
+
assert.validationError(function() {
|
|
74
|
+
p5._validateParameters('arc', [1, 1, 10.5, 10, 0, undefined, 'pie']);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
test('arc(): missing param #6, no friendly-err-msg', function() {
|
|
78
|
+
assert.doesNotThrow(
|
|
79
|
+
function() {
|
|
80
|
+
p5._validateParameters('arc', [1, 1, 10.5, 10, 0, Math.PI]);
|
|
81
|
+
},
|
|
82
|
+
Error,
|
|
83
|
+
'got unwanted exception'
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
test('arc(): wrong param type at #0', function() {
|
|
87
|
+
assert.validationError(function() {
|
|
88
|
+
p5._validateParameters('arc', ['a', 1, 10.5, 10, 0, Math.PI, 'pie']);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
suite('validateParameters: Numbers + optional Constant', function() {
|
|
94
|
+
test('rect(): no friendly-err-msg', function() {
|
|
95
|
+
assert.doesNotThrow(
|
|
96
|
+
function() {
|
|
97
|
+
p5._validateParameters('rect', [1, 1, 10.5, 10]);
|
|
98
|
+
},
|
|
99
|
+
Error,
|
|
100
|
+
'got unwanted exception'
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
test('rect(): wrong param type at #0', function() {
|
|
104
|
+
assert.validationError(function() {
|
|
105
|
+
p5._validateParameters('rect', ['a', 1, 10.5, 10, 0, Math.PI]);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
suite(
|
|
111
|
+
'validateParameters: class, multi-types + optional Numbers',
|
|
112
|
+
function() {
|
|
113
|
+
test('ambientLight(): no friendly-err-msg', function() {
|
|
114
|
+
assert.doesNotThrow(
|
|
115
|
+
function() {
|
|
116
|
+
var c = myp5.color(255, 204, 0);
|
|
117
|
+
p5._validateParameters('ambientLight', [c]);
|
|
118
|
+
},
|
|
119
|
+
Error,
|
|
120
|
+
'got unwanted exception'
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
suite('validateParameters: a few edge cases', function() {
|
|
127
|
+
// testing for edge cases mentioned in
|
|
128
|
+
// https://github.com/processing/p5.js/issues/2740
|
|
129
|
+
testUnMinified('color: wrong type for optional parameter', function() {
|
|
130
|
+
let err = assert.throws(function() {
|
|
131
|
+
p5._validateParameters('color', [0, 0, 0, 'A']);
|
|
132
|
+
}, p5.ValidationError);
|
|
133
|
+
assert.strictEqual(
|
|
134
|
+
err.type,
|
|
135
|
+
'WRONG_TYPE',
|
|
136
|
+
'ValidationError type is correct'
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
testUnMinified('color: superfluous parameter', function() {
|
|
141
|
+
assert.throws(function() {
|
|
142
|
+
p5._validateParameters('color', [[0, 0, 0], 0]);
|
|
143
|
+
}, p5.ValidationError);
|
|
144
|
+
// not performing a type check here as it could reasonably fit as
|
|
145
|
+
// either WRONG_TYPE or TOO_MANY_ARGUMENTS
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
testUnMinified('color: wrong element types', function() {
|
|
149
|
+
let err = assert.throws(function() {
|
|
150
|
+
p5._validateParameters('color', [['A', 'B', 'C']]);
|
|
151
|
+
}, p5.ValidationError);
|
|
152
|
+
assert.strictEqual(
|
|
153
|
+
err.type,
|
|
154
|
+
'WRONG_TYPE',
|
|
155
|
+
'ValidationError type is correct'
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
testUnMinified('rect: null, non-trailing, optional parameter', function() {
|
|
160
|
+
let err = assert.throws(function() {
|
|
161
|
+
p5._validateParameters('rect', [0, 0, 0, 0, null, 0, 0, 0]);
|
|
162
|
+
}, p5.ValidationError);
|
|
163
|
+
assert.strictEqual(
|
|
164
|
+
err.type,
|
|
165
|
+
'EMPTY_VAR',
|
|
166
|
+
'ValidationError type is correct'
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
testUnMinified('color: too many args + wrong types too', function() {
|
|
171
|
+
let err = assert.throws(function() {
|
|
172
|
+
p5._validateParameters('color', ['A', 'A', 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
173
|
+
}, p5.ValidationError);
|
|
174
|
+
assert.strictEqual(
|
|
175
|
+
err.type,
|
|
176
|
+
'TOO_MANY_ARGUMENTS',
|
|
177
|
+
'ValidationError type is correct'
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
testUnMinified('line: null string given', function() {
|
|
182
|
+
let err = assert.throws(function() {
|
|
183
|
+
p5._validateParameters('line', [1, 2, 4, 'null']);
|
|
184
|
+
}, p5.ValidationError);
|
|
185
|
+
assert.strictEqual(
|
|
186
|
+
err.type,
|
|
187
|
+
'WRONG_TYPE',
|
|
188
|
+
'ValidationError type is correct'
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
testUnMinified('line: NaN value given', function() {
|
|
193
|
+
let err = assert.throws(function() {
|
|
194
|
+
p5._validateParameters('line', [1, 2, 4, NaN]);
|
|
195
|
+
}, p5.ValidationError);
|
|
196
|
+
assert.strictEqual(
|
|
197
|
+
err.type,
|
|
198
|
+
'WRONG_TYPE',
|
|
199
|
+
'ValidationError type is correct'
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
suite('validateParameters: trailing undefined arguments', function() {
|
|
205
|
+
// see https://github.com/processing/p5.js/issues/4571 for details
|
|
206
|
+
|
|
207
|
+
test('color: missing params #1 #2', function() {
|
|
208
|
+
// even though color can also be called with one argument, if 3 args
|
|
209
|
+
// are passed, it is likely that them being undefined is an accident
|
|
210
|
+
assert.validationError(function() {
|
|
211
|
+
p5._validateParameters('color', [12, undefined, undefined]);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('random: missing params #0 #1 (both optional)', function() {
|
|
216
|
+
// even though the undefined params are optional, since they are passed
|
|
217
|
+
// to the function, it is more likely that the user wanted to call the
|
|
218
|
+
// function with 2 arguments.
|
|
219
|
+
assert.validationError(function() {
|
|
220
|
+
p5._validateParameters('random', [undefined, undefined]);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// compuslory argument trailing undefined
|
|
225
|
+
testUnMinified('circle: missing compulsory param #2', function() {
|
|
226
|
+
// should throw an EMPTY_VAR error instead of a TOO_FEW_ARGUMENTS error
|
|
227
|
+
let err = assert.throws(function() {
|
|
228
|
+
p5._validateParameters('circle', [5, 5, undefined]);
|
|
229
|
+
}, p5.ValidationError);
|
|
230
|
+
assert.strictEqual(
|
|
231
|
+
err.type,
|
|
232
|
+
'EMPTY_VAR',
|
|
233
|
+
'ValidationError type is correct'
|
|
234
|
+
);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
suite('validateParameters: argument tree', function() {
|
|
239
|
+
// should not throw a validation error for the same kind of wrong args
|
|
240
|
+
// more than once. This prevents repetetive validation logs for a
|
|
241
|
+
// function that is called in a loop or draw()
|
|
242
|
+
testUnMinified(
|
|
243
|
+
'no repeated validation error for the same wrong arguments',
|
|
244
|
+
function() {
|
|
245
|
+
assert.validationError(function() {
|
|
246
|
+
myp5.color();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
assert.doesNotThrow(
|
|
250
|
+
function() {
|
|
251
|
+
myp5.color(); // Same type of wrong arguments as above
|
|
252
|
+
},
|
|
253
|
+
p5.ValidationError,
|
|
254
|
+
'got unwanted ValidationError'
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
testUnMinified(
|
|
260
|
+
'should throw validation errors for different wrong args',
|
|
261
|
+
function() {
|
|
262
|
+
assert.validationError(function() {
|
|
263
|
+
myp5.color();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
assert.validationError(function() {
|
|
267
|
+
myp5.color(false);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
testUnMinified('arg tree is built properly', function() {
|
|
273
|
+
let myArgTree = p5._getValidateParamsArgTree();
|
|
274
|
+
myp5.random();
|
|
275
|
+
myp5.random(50);
|
|
276
|
+
myp5.random([50, 70, 10]);
|
|
277
|
+
assert.strictEqual(
|
|
278
|
+
myArgTree.random.seen,
|
|
279
|
+
true,
|
|
280
|
+
'tree built correctly for random()'
|
|
281
|
+
);
|
|
282
|
+
assert.strictEqual(
|
|
283
|
+
myArgTree.random.number.seen,
|
|
284
|
+
true,
|
|
285
|
+
'tree built correctly for random(min: Number)'
|
|
286
|
+
);
|
|
287
|
+
assert.strictEqual(
|
|
288
|
+
myArgTree.random.as.number.number.number.seen,
|
|
289
|
+
true,
|
|
290
|
+
'tree built correctly for random(choices: Array)'
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
let c = myp5.color(10);
|
|
294
|
+
myp5.alpha(c);
|
|
295
|
+
assert.strictEqual(
|
|
296
|
+
myArgTree.color.number.seen,
|
|
297
|
+
true,
|
|
298
|
+
'tree built correctly for color(gray: Number)'
|
|
299
|
+
);
|
|
300
|
+
assert.strictEqual(
|
|
301
|
+
myArgTree.alpha.Color.seen,
|
|
302
|
+
true,
|
|
303
|
+
'tree built correctly for alpha(color: p5.Color)'
|
|
304
|
+
);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
suite('validateParameters: multi-format', function() {
|
|
309
|
+
test('color(): no friendly-err-msg', function() {
|
|
310
|
+
assert.doesNotThrow(
|
|
311
|
+
function() {
|
|
312
|
+
p5._validateParameters('color', [65]);
|
|
313
|
+
},
|
|
314
|
+
Error,
|
|
315
|
+
'got unwanted exception'
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
test('color(): no friendly-err-msg', function() {
|
|
319
|
+
assert.doesNotThrow(
|
|
320
|
+
function() {
|
|
321
|
+
p5._validateParameters('color', [65, 0.5]);
|
|
322
|
+
},
|
|
323
|
+
Error,
|
|
324
|
+
'got unwanted exception'
|
|
325
|
+
);
|
|
326
|
+
});
|
|
327
|
+
test('color(): no friendly-err-msg', function() {
|
|
328
|
+
assert.doesNotThrow(
|
|
329
|
+
function() {
|
|
330
|
+
p5._validateParameters('color', [255, 204, 0]);
|
|
331
|
+
},
|
|
332
|
+
Error,
|
|
333
|
+
'got unwanted exception'
|
|
334
|
+
);
|
|
335
|
+
});
|
|
336
|
+
test('color(): optional parameter, incorrect type', function() {
|
|
337
|
+
assert.validationError(function() {
|
|
338
|
+
p5._validateParameters('color', [0, 0, 0, 'A']);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
test('color(): extra parameter', function() {
|
|
342
|
+
assert.validationError(function() {
|
|
343
|
+
p5._validateParameters('color', [[0, 0, 0], 0]);
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
test('color(): incorrect element type', function() {
|
|
347
|
+
assert.validationError(function() {
|
|
348
|
+
p5._validateParameters('color', [['A', 'B', 'C']]);
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
test('color(): incorrect parameter count', function() {
|
|
352
|
+
assert.validationError(function() {
|
|
353
|
+
p5._validateParameters('color', ['A', 'A', 0, 0, 0, 0, 0, 0]);
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
suite('helpForMisusedAtTopLevelCode', function() {
|
|
359
|
+
var help = function(msg) {
|
|
360
|
+
var log = [];
|
|
361
|
+
var logger = function(msg) {
|
|
362
|
+
log.push(msg);
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
p5.prototype._helpForMisusedAtTopLevelCode({ message: msg }, logger);
|
|
366
|
+
assert.equal(log.length, 1);
|
|
367
|
+
return log[0];
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
test('help for constants is shown', function() {
|
|
371
|
+
assert.match(
|
|
372
|
+
help("'HALF_PI' is undefined"),
|
|
373
|
+
/Did you just try to use p5\.js's HALF_PI constant\?/
|
|
374
|
+
);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test('help for functions is shown', function() {
|
|
378
|
+
assert.match(
|
|
379
|
+
help("'smooth' is undefined"),
|
|
380
|
+
/Did you just try to use p5\.js's smooth\(\) function\?/
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test('help for variables is shown', function() {
|
|
385
|
+
assert.match(
|
|
386
|
+
help("'focused' is undefined"),
|
|
387
|
+
/Did you just try to use p5\.js's focused variable\?/
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
suite('misspelling detection', function() {
|
|
393
|
+
let log = [];
|
|
394
|
+
const logger = function(err) {
|
|
395
|
+
log.push(err);
|
|
396
|
+
};
|
|
397
|
+
let help = function(err) {
|
|
398
|
+
p5._fesErrorMonitor(err);
|
|
399
|
+
assert.equal(log.length, 1);
|
|
400
|
+
return log[0];
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
setup(function() {
|
|
404
|
+
log = [];
|
|
405
|
+
p5._fesLogger = logger;
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
teardown(function() {
|
|
409
|
+
p5._fesLogger = null;
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
testUnMinified('detects capitalization mistakes', function() {
|
|
413
|
+
const logMsg = help(new ReferenceError('MouseX is not defined'));
|
|
414
|
+
assert.match(
|
|
415
|
+
logMsg,
|
|
416
|
+
/It seems that you may have accidentally written "MouseX"/
|
|
417
|
+
);
|
|
418
|
+
assert.match(logMsg, /mouseX/);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
testUnMinified('detects spelling mistakes', function() {
|
|
422
|
+
const logMsg = help(new ReferenceError('colour is not defined'));
|
|
423
|
+
assert.match(
|
|
424
|
+
logMsg,
|
|
425
|
+
/It seems that you may have accidentally written "colour"/
|
|
426
|
+
);
|
|
427
|
+
assert.match(logMsg, /color/);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
testUnMinified(
|
|
431
|
+
'can give more than one closest matches, if applicable',
|
|
432
|
+
function() {
|
|
433
|
+
const logMsg = help(new ReferenceError('strok is not defined'));
|
|
434
|
+
assert.match(
|
|
435
|
+
logMsg,
|
|
436
|
+
/It seems that you may have accidentally written "strok"/
|
|
437
|
+
);
|
|
438
|
+
assert.match(logMsg, /stroke/);
|
|
439
|
+
assert.match(logMsg, /STROKE/);
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
testUnMinified('detects spelling + captialization mistakes', function() {
|
|
444
|
+
const logMsg = help(new ReferenceError('RandomGossian is not defined'));
|
|
445
|
+
assert.match(
|
|
446
|
+
logMsg,
|
|
447
|
+
/It seems that you may have accidentally written "RandomGossian"/
|
|
448
|
+
);
|
|
449
|
+
assert.match(logMsg, /randomGaussian/);
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
suite('caps mistakes for user-defined functions (instance mode)', function() {
|
|
454
|
+
let myp5;
|
|
455
|
+
let log;
|
|
456
|
+
const logger = function(err) {
|
|
457
|
+
log.push(err);
|
|
458
|
+
};
|
|
459
|
+
setup(function(done) {
|
|
460
|
+
log = [];
|
|
461
|
+
p5._fesLogger = logger;
|
|
462
|
+
new p5(function(p) {
|
|
463
|
+
// intentional capitalization mistake
|
|
464
|
+
p.preLoad = function() {};
|
|
465
|
+
p.setup = function() {
|
|
466
|
+
myp5 = p;
|
|
467
|
+
p._fesLogger = logger;
|
|
468
|
+
done();
|
|
469
|
+
};
|
|
470
|
+
});
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
teardown(function() {
|
|
474
|
+
p5._fesLogger = null;
|
|
475
|
+
myp5.remove();
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
testUnMinified(
|
|
479
|
+
'detects capitatilization mistake in instance mode',
|
|
480
|
+
function() {
|
|
481
|
+
assert.strictEqual(log.length, 1, 'One message is displayed');
|
|
482
|
+
assert.match(
|
|
483
|
+
log[0],
|
|
484
|
+
/It seems that you may have accidentally written preLoad instead of preload/
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
suite('caps mistakes for user-defined functions (global mode)', function() {
|
|
491
|
+
let log;
|
|
492
|
+
const logger = function(err) {
|
|
493
|
+
log.push(err);
|
|
494
|
+
};
|
|
495
|
+
testUnMinified(
|
|
496
|
+
'detects capitatilization mistake in global mode',
|
|
497
|
+
function() {
|
|
498
|
+
return new Promise(function(resolve) {
|
|
499
|
+
iframe = createP5Iframe(
|
|
500
|
+
[
|
|
501
|
+
P5_SCRIPT_TAG,
|
|
502
|
+
'<script>',
|
|
503
|
+
'p5._fesLogger = window.logger',
|
|
504
|
+
'function setup() { window.afterSetup();}',
|
|
505
|
+
'function DRAW() {}',
|
|
506
|
+
'</script>'
|
|
507
|
+
].join('\n')
|
|
508
|
+
);
|
|
509
|
+
log = [];
|
|
510
|
+
iframe.elt.contentWindow.logger = logger;
|
|
511
|
+
iframe.elt.contentWindow.afterSetup = resolve;
|
|
512
|
+
}).then(function() {
|
|
513
|
+
//let log = iframe.elt.contentWindow.log;
|
|
514
|
+
assert.strictEqual(log.length, 1);
|
|
515
|
+
assert.match(
|
|
516
|
+
log[0],
|
|
517
|
+
/It seems that you may have accidentally written DRAW instead of draw/
|
|
518
|
+
);
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// seperating in another suite because these don't need to initialize myp5
|
|
526
|
+
// for each test. Instead they initialize p5 in the iframe. These tests are
|
|
527
|
+
// also slower than the above ones.
|
|
528
|
+
suite('Global Error Handling', function() {
|
|
529
|
+
let log;
|
|
530
|
+
const WAIT_AND_RESOLVE = [
|
|
531
|
+
'<script>',
|
|
532
|
+
'p5._fesLogger = window.logger',
|
|
533
|
+
'let flag = false;',
|
|
534
|
+
'setInterval(() => {',
|
|
535
|
+
// just because the log has one element doesn't necessarily mean that the
|
|
536
|
+
// handler has finished its job. The flag allows it to take some more time
|
|
537
|
+
// after adding the first log message
|
|
538
|
+
' if (window.logger.length > 0) {',
|
|
539
|
+
' if (flag) window.afterSetup();',
|
|
540
|
+
' flag = true;',
|
|
541
|
+
' }',
|
|
542
|
+
'}, 50);',
|
|
543
|
+
'</script>'
|
|
544
|
+
].join('\n');
|
|
545
|
+
const logger = function(err) {
|
|
546
|
+
log.push(err);
|
|
547
|
+
};
|
|
548
|
+
setup(function() {
|
|
549
|
+
log = [];
|
|
550
|
+
p5._fesLogger = logger;
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
teardown(function() {
|
|
554
|
+
p5._fesLogger = null;
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
const prepSyntaxTest = (arr, resolve) => {
|
|
558
|
+
iframe = createP5Iframe(
|
|
559
|
+
[P5_SCRIPT_TAG, WAIT_AND_RESOLVE, '<script>', ...arr, '</script>'].join(
|
|
560
|
+
'\n'
|
|
561
|
+
)
|
|
562
|
+
);
|
|
563
|
+
log = [];
|
|
564
|
+
iframe.elt.contentWindow.logger = logger;
|
|
565
|
+
iframe.elt.contentWindow.afterSetup = resolve;
|
|
566
|
+
return iframe;
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
testUnMinified('identifies errors happenning internally', function() {
|
|
570
|
+
return new Promise(function(resolve) {
|
|
571
|
+
// quite an unusual way to test, but the error listener doesn't work
|
|
572
|
+
// under mocha. Also the stacktrace gets filled with mocha internal
|
|
573
|
+
// function calls. Using this method solves both of these problems.
|
|
574
|
+
// This method also allows us to test for SyntaxError without messing
|
|
575
|
+
// with flow of the other tests
|
|
576
|
+
prepSyntaxTest(
|
|
577
|
+
[
|
|
578
|
+
'function setup() {',
|
|
579
|
+
'let cnv = createCanvas(400, 400);',
|
|
580
|
+
'cnv.mouseClicked();', // Error in p5 library as no callback passed
|
|
581
|
+
'}'
|
|
582
|
+
],
|
|
583
|
+
resolve
|
|
584
|
+
);
|
|
585
|
+
}).then(function() {
|
|
586
|
+
assert.strictEqual(log.length, 1);
|
|
587
|
+
assert.match(log[0], /inside the p5js library/);
|
|
588
|
+
assert.match(log[0], /mouseClicked/);
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
testUnMinified(
|
|
593
|
+
'identifies errors happenning internally in ES6 classes',
|
|
594
|
+
function() {
|
|
595
|
+
return new Promise(function(resolve) {
|
|
596
|
+
prepSyntaxTest(
|
|
597
|
+
[
|
|
598
|
+
'function setup() {',
|
|
599
|
+
'let cnv = createCanvas(10, 10, WEBGL);',
|
|
600
|
+
'let fbo = createFramebuffer();',
|
|
601
|
+
'fbo.draw();', // Error in p5 library as no callback passed
|
|
602
|
+
'}'
|
|
603
|
+
],
|
|
604
|
+
resolve
|
|
605
|
+
);
|
|
606
|
+
}).then(function() {
|
|
607
|
+
assert.strictEqual(log.length, 1);
|
|
608
|
+
assert.match(log[0], /inside the p5js library/);
|
|
609
|
+
assert.match(log[0], /draw/);
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
testUnMinified('identifies errors in preload', function() {
|
|
615
|
+
return new Promise(function(resolve) {
|
|
616
|
+
prepSyntaxTest(
|
|
617
|
+
[
|
|
618
|
+
'function preload() {',
|
|
619
|
+
'circle(5, 5, 2);', // error
|
|
620
|
+
'}',
|
|
621
|
+
'function setup() {',
|
|
622
|
+
'createCanvas(10, 10);',
|
|
623
|
+
'}'
|
|
624
|
+
],
|
|
625
|
+
resolve
|
|
626
|
+
);
|
|
627
|
+
}).then(function() {
|
|
628
|
+
assert.strictEqual(log.length, 1);
|
|
629
|
+
assert.match(log[0], /"circle" being called from preload/);
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
testUnMinified("identifies TypeError 'notDefined'", function() {
|
|
634
|
+
return new Promise(function(resolve) {
|
|
635
|
+
prepSyntaxTest(
|
|
636
|
+
[
|
|
637
|
+
'function setup() {',
|
|
638
|
+
'let x = asdfg + 5;', // ReferenceError: asdfg is not defined
|
|
639
|
+
'}'
|
|
640
|
+
],
|
|
641
|
+
resolve
|
|
642
|
+
);
|
|
643
|
+
}).then(function() {
|
|
644
|
+
assert.strictEqual(log.length, 1);
|
|
645
|
+
assert.match(log[0], /asdfg/);
|
|
646
|
+
assert.match(log[0], /not defined in the current scope/);
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
testUnMinified(
|
|
651
|
+
"identifies SyntaxError 'Invalid or unexpected Token'",
|
|
652
|
+
function() {
|
|
653
|
+
return new Promise(function(resolve) {
|
|
654
|
+
prepSyntaxTest(
|
|
655
|
+
[
|
|
656
|
+
'function setup() {',
|
|
657
|
+
'let x = “not a string”', // SyntaxError: Invalid or unexpected token
|
|
658
|
+
'}'
|
|
659
|
+
],
|
|
660
|
+
resolve
|
|
661
|
+
);
|
|
662
|
+
}).then(function() {
|
|
663
|
+
assert.strictEqual(log.length, 1);
|
|
664
|
+
assert.match(log[0], /Syntax Error/);
|
|
665
|
+
assert.match(log[0], /JavaScript doesn't recognize/);
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
testUnMinified("identifies SyntaxError 'unexpectedToken'", function() {
|
|
671
|
+
return new Promise(function(resolve) {
|
|
672
|
+
prepSyntaxTest(
|
|
673
|
+
[
|
|
674
|
+
'function setup() {',
|
|
675
|
+
'for (let i = 0; i < 5,; ++i) {}', // SyntaxError: Unexpected token
|
|
676
|
+
'}'
|
|
677
|
+
],
|
|
678
|
+
resolve
|
|
679
|
+
);
|
|
680
|
+
}).then(function() {
|
|
681
|
+
assert.strictEqual(log.length, 1);
|
|
682
|
+
assert.match(log[0], /Syntax Error/);
|
|
683
|
+
assert.match(log[0], /typo/);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
testUnMinified("identifies TypeError 'notFunc'", function() {
|
|
688
|
+
return new Promise(function(resolve) {
|
|
689
|
+
prepSyntaxTest(
|
|
690
|
+
[
|
|
691
|
+
'function setup() {',
|
|
692
|
+
'let asdfg = 5',
|
|
693
|
+
'asdfg()', // TypeError: asdfg is not a function
|
|
694
|
+
'}'
|
|
695
|
+
],
|
|
696
|
+
resolve
|
|
697
|
+
);
|
|
698
|
+
}).then(function() {
|
|
699
|
+
assert.strictEqual(log.length, 1);
|
|
700
|
+
assert.match(log[0], /"asdfg" could not be called as a function/);
|
|
701
|
+
});
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
testUnMinified("identifies TypeError 'notFuncObj'", function() {
|
|
705
|
+
return new Promise(function(resolve) {
|
|
706
|
+
prepSyntaxTest(
|
|
707
|
+
[
|
|
708
|
+
'function setup() {',
|
|
709
|
+
'let asdfg = {}',
|
|
710
|
+
'asdfg.abcd()', // TypeError: abcd is not a function
|
|
711
|
+
'}'
|
|
712
|
+
],
|
|
713
|
+
resolve
|
|
714
|
+
);
|
|
715
|
+
}).then(function() {
|
|
716
|
+
assert.strictEqual(log.length, 1);
|
|
717
|
+
assert.match(log[0], /"abcd" could not be called as a function/);
|
|
718
|
+
assert.match(log[0], /"asdfg" has "abcd" in it/);
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
testUnMinified("identifies ReferenceError 'cannotAccess'", function() {
|
|
723
|
+
return new Promise(function(resolve) {
|
|
724
|
+
prepSyntaxTest(
|
|
725
|
+
[
|
|
726
|
+
'function setup() {',
|
|
727
|
+
'console.log(x)', // ReferenceError: Cannot access 'x' before initialization
|
|
728
|
+
'let x = 100',
|
|
729
|
+
'}'
|
|
730
|
+
],
|
|
731
|
+
resolve
|
|
732
|
+
);
|
|
733
|
+
}).then(function() {
|
|
734
|
+
assert.strictEqual(log.length, 1);
|
|
735
|
+
assert.match(log[0], /Error/);
|
|
736
|
+
assert.match(log[0], /used before declaration/);
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
testUnMinified("identifies SyntaxError 'badReturnOrYield'", function() {
|
|
741
|
+
return new Promise(function(resolve) {
|
|
742
|
+
prepSyntaxTest(
|
|
743
|
+
['function setup() {', 'let x = 100;', '}', 'return;'],
|
|
744
|
+
resolve
|
|
745
|
+
);
|
|
746
|
+
}).then(function() {
|
|
747
|
+
assert.strictEqual(log.length, 1);
|
|
748
|
+
assert.match(log[0], /Syntax Error/);
|
|
749
|
+
assert.match(log[0], /lies outside of a function/);
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
testUnMinified("identifies SyntaxError 'missingInitializer'", function() {
|
|
754
|
+
return new Promise(function(resolve) {
|
|
755
|
+
prepSyntaxTest(
|
|
756
|
+
[
|
|
757
|
+
'function setup() {',
|
|
758
|
+
'const x;', //SyntaxError: Missing initializer in const declaration
|
|
759
|
+
'}'
|
|
760
|
+
],
|
|
761
|
+
resolve
|
|
762
|
+
);
|
|
763
|
+
}).then(function() {
|
|
764
|
+
assert.strictEqual(log.length, 1);
|
|
765
|
+
assert.match(log[0], /Syntax Error/);
|
|
766
|
+
assert.match(log[0], /but not initialized/);
|
|
767
|
+
});
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
testUnMinified("identifies SyntaxError 'redeclaredVariable'", function() {
|
|
771
|
+
return new Promise(function(resolve) {
|
|
772
|
+
prepSyntaxTest(
|
|
773
|
+
[
|
|
774
|
+
'function setup() {',
|
|
775
|
+
'let x=100;',
|
|
776
|
+
'let x=99;', //SyntaxError: Identifier 'x' has already been declared
|
|
777
|
+
'}'
|
|
778
|
+
],
|
|
779
|
+
resolve
|
|
780
|
+
);
|
|
781
|
+
}).then(function() {
|
|
782
|
+
assert.strictEqual(log.length, 1);
|
|
783
|
+
assert.match(log[0], /Syntax Error/);
|
|
784
|
+
assert.match(log[0], /JavaScript doesn't allow/);
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
testUnMinified("identifies TypeError 'constAssign'", function() {
|
|
789
|
+
return new Promise(function(resolve) {
|
|
790
|
+
prepSyntaxTest(
|
|
791
|
+
[
|
|
792
|
+
'function setup() {',
|
|
793
|
+
'const x = 100;',
|
|
794
|
+
'x = 10;', //TypeError: Assignment to constant variable
|
|
795
|
+
'}'
|
|
796
|
+
],
|
|
797
|
+
resolve
|
|
798
|
+
);
|
|
799
|
+
}).then(function() {
|
|
800
|
+
assert.strictEqual(log.length, 1);
|
|
801
|
+
assert.match(log[0], /Error/);
|
|
802
|
+
assert.match(log[0], /const variable is being/);
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
testUnMinified("identifies TypeError 'readFromNull'", function() {
|
|
807
|
+
return new Promise(function(resolve) {
|
|
808
|
+
prepSyntaxTest(
|
|
809
|
+
[
|
|
810
|
+
'function setup() {',
|
|
811
|
+
'const x = null;',
|
|
812
|
+
'console.log(x.prop);', //TypeError: Cannot read property 'prop' of null
|
|
813
|
+
'}'
|
|
814
|
+
],
|
|
815
|
+
resolve
|
|
816
|
+
);
|
|
817
|
+
}).then(function() {
|
|
818
|
+
assert.strictEqual(log.length, 1);
|
|
819
|
+
assert.match(log[0], /Error/);
|
|
820
|
+
assert.match(log[0], /property of null/);
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
testUnMinified("identifies TypeError 'readFromUndefined'", function() {
|
|
825
|
+
return new Promise(function(resolve) {
|
|
826
|
+
prepSyntaxTest(
|
|
827
|
+
[
|
|
828
|
+
'function setup() {',
|
|
829
|
+
'const x = undefined;',
|
|
830
|
+
'console.log(x.prop);', //TypeError: Cannot read property 'prop' of undefined
|
|
831
|
+
'}'
|
|
832
|
+
],
|
|
833
|
+
resolve
|
|
834
|
+
);
|
|
835
|
+
}).then(function() {
|
|
836
|
+
assert.strictEqual(log.length, 1);
|
|
837
|
+
assert.match(log[0], /Error/);
|
|
838
|
+
assert.match(log[0], /property of undefined/);
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
testUnMinified('builds friendlyStack', function() {
|
|
843
|
+
return new Promise(function(resolve) {
|
|
844
|
+
prepSyntaxTest(
|
|
845
|
+
[
|
|
846
|
+
'function myfun(){',
|
|
847
|
+
'asdfg()', // ReferenceError
|
|
848
|
+
'}',
|
|
849
|
+
'function setup() {',
|
|
850
|
+
'myfun()',
|
|
851
|
+
'}'
|
|
852
|
+
],
|
|
853
|
+
resolve
|
|
854
|
+
);
|
|
855
|
+
}).then(function() {
|
|
856
|
+
assert.strictEqual(log.length, 2);
|
|
857
|
+
let temp = log[1].split('\n');
|
|
858
|
+
temp = temp.filter(e => e.trim().length > 0);
|
|
859
|
+
assert.strictEqual(temp.length, 4);
|
|
860
|
+
assert.match(log[0], /"asdfg" is not defined/);
|
|
861
|
+
assert.match(temp[1], /Error at/);
|
|
862
|
+
assert.match(temp[1], /myfun/);
|
|
863
|
+
assert.match(temp[3], /Called from/);
|
|
864
|
+
assert.match(temp[3], /setup/);
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
|
|
868
|
+
testUnMinified('indentifies internal error - instance mode', function() {
|
|
869
|
+
return new Promise(function(resolve) {
|
|
870
|
+
prepSyntaxTest(
|
|
871
|
+
[
|
|
872
|
+
'function sketch(p) {',
|
|
873
|
+
' p.setup = function() {',
|
|
874
|
+
' p.stroke();', // error
|
|
875
|
+
' }',
|
|
876
|
+
'}',
|
|
877
|
+
'new p5(sketch);'
|
|
878
|
+
],
|
|
879
|
+
resolve
|
|
880
|
+
);
|
|
881
|
+
}).then(function() {
|
|
882
|
+
assert.strictEqual(log.length, 1);
|
|
883
|
+
assert.match(log[0], /stroke/);
|
|
884
|
+
assert.match(log[0], /inside the p5js library/);
|
|
885
|
+
});
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
testUnMinified('indentifies error in preload - instance mode', function() {
|
|
889
|
+
return new Promise(function(resolve) {
|
|
890
|
+
prepSyntaxTest(
|
|
891
|
+
[
|
|
892
|
+
'function sketch(p) {',
|
|
893
|
+
' p.preload = function() {',
|
|
894
|
+
' p.circle(2, 2, 2);', // error
|
|
895
|
+
' }',
|
|
896
|
+
' p.setup = function() {',
|
|
897
|
+
' p.createCanvas(5, 5);',
|
|
898
|
+
' }',
|
|
899
|
+
'}',
|
|
900
|
+
'new p5(sketch);'
|
|
901
|
+
],
|
|
902
|
+
resolve
|
|
903
|
+
);
|
|
904
|
+
}).then(function() {
|
|
905
|
+
assert.strictEqual(log.length, 1);
|
|
906
|
+
assert.match(log[0], /"circle" being called from preload/);
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
testUnMinified('indentifies error in user code - instance mode', function() {
|
|
911
|
+
return new Promise(function(resolve) {
|
|
912
|
+
prepSyntaxTest(
|
|
913
|
+
[
|
|
914
|
+
'function sketch(p) {',
|
|
915
|
+
' p.setup = function() {',
|
|
916
|
+
' myfun();', // ReferenceError: myfun is not defined
|
|
917
|
+
' }',
|
|
918
|
+
'}',
|
|
919
|
+
'new p5(sketch);'
|
|
920
|
+
],
|
|
921
|
+
resolve
|
|
922
|
+
);
|
|
923
|
+
}).then(function() {
|
|
924
|
+
assert.strictEqual(log.length, 1);
|
|
925
|
+
assert.match(log[0], /myfun/);
|
|
926
|
+
assert.match(log[0], /is not defined in the current scope/);
|
|
927
|
+
});
|
|
928
|
+
});
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
suite('Tests for p5.js sketch_reader', function() {
|
|
932
|
+
const WAIT_AND_RESOLVE = [
|
|
933
|
+
'<script>',
|
|
934
|
+
'p5._fesLogger = window.logger',
|
|
935
|
+
'let flag = false;',
|
|
936
|
+
'setInterval(() => {',
|
|
937
|
+
// just because the log has one element doesn't necessarily mean that the
|
|
938
|
+
// handler has finished its job. The flag allows it to take some more time
|
|
939
|
+
// after adding the first log message
|
|
940
|
+
' if (window.logger.length > 0) {',
|
|
941
|
+
' if (flag) window.afterSetup();',
|
|
942
|
+
' flag = true;',
|
|
943
|
+
' }',
|
|
944
|
+
'}, 50);',
|
|
945
|
+
'</script>'
|
|
946
|
+
].join('\n');
|
|
947
|
+
|
|
948
|
+
let log;
|
|
949
|
+
const logger = function(err) {
|
|
950
|
+
log.push(err);
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
const prepSketchReaderTest = (arr, resolve) => {
|
|
954
|
+
iframe = createP5Iframe(
|
|
955
|
+
[P5_SCRIPT_TAG, WAIT_AND_RESOLVE, '<script>', ...arr, '</script>'].join(
|
|
956
|
+
'\n'
|
|
957
|
+
)
|
|
958
|
+
);
|
|
959
|
+
log = [];
|
|
960
|
+
iframe.elt.contentWindow.logger = logger;
|
|
961
|
+
iframe.elt.contentWindow.afterSetup = resolve;
|
|
962
|
+
return iframe;
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
testUnMinified(
|
|
966
|
+
'detects reassignment of p5.js constant inside setup',
|
|
967
|
+
function() {
|
|
968
|
+
return new Promise(function(resolve) {
|
|
969
|
+
prepSketchReaderTest(
|
|
970
|
+
['function setup() {', 'let PI = 100', '}'],
|
|
971
|
+
resolve
|
|
972
|
+
);
|
|
973
|
+
}).then(function() {
|
|
974
|
+
assert.strictEqual(log.length, 1);
|
|
975
|
+
assert.match(log[0], /you have used a p5.js reserved variable/);
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
);
|
|
979
|
+
|
|
980
|
+
testUnMinified(
|
|
981
|
+
'detects reassignment of p5.js function inside setup',
|
|
982
|
+
function() {
|
|
983
|
+
return new Promise(function(resolve) {
|
|
984
|
+
prepSketchReaderTest(
|
|
985
|
+
['function setup() {', 'let text = 100', '}'],
|
|
986
|
+
resolve
|
|
987
|
+
);
|
|
988
|
+
}).then(function() {
|
|
989
|
+
assert.strictEqual(log.length, 1);
|
|
990
|
+
assert.match(log[0], /you have used a p5.js reserved function/);
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
);
|
|
994
|
+
|
|
995
|
+
testUnMinified(
|
|
996
|
+
'detects reassignment of p5.js constant outside setup',
|
|
997
|
+
function() {
|
|
998
|
+
return new Promise(function(resolve) {
|
|
999
|
+
prepSketchReaderTest(['let PI = 100', 'function setup() {}'], resolve);
|
|
1000
|
+
}).then(function() {
|
|
1001
|
+
assert.strictEqual(log.length, 1);
|
|
1002
|
+
assert.match(log[0], /you have used a p5.js reserved variable/);
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
);
|
|
1006
|
+
|
|
1007
|
+
testUnMinified(
|
|
1008
|
+
'detects reassignment of p5.js function (text) outside setup',
|
|
1009
|
+
function() {
|
|
1010
|
+
return new Promise(function(resolve) {
|
|
1011
|
+
prepSketchReaderTest(
|
|
1012
|
+
['let text = 100', 'function setup() {}'],
|
|
1013
|
+
resolve
|
|
1014
|
+
);
|
|
1015
|
+
}).then(function() {
|
|
1016
|
+
assert.strictEqual(log.length, 1);
|
|
1017
|
+
assert.match(log[0], /you have used a p5.js reserved function/);
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
);
|
|
1021
|
+
|
|
1022
|
+
testUnMinified(
|
|
1023
|
+
'detects reassignment of p5.js function (textSize from Typography) outside setup',
|
|
1024
|
+
function() {
|
|
1025
|
+
return new Promise(function(resolve) {
|
|
1026
|
+
prepSketchReaderTest(
|
|
1027
|
+
['let textSize = 100', 'function setup() {}'],
|
|
1028
|
+
resolve
|
|
1029
|
+
);
|
|
1030
|
+
}).then(function() {
|
|
1031
|
+
assert.strictEqual(log.length, 1);
|
|
1032
|
+
assert.match(log[0], /you have used a p5.js reserved function/);
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
);
|
|
1036
|
+
|
|
1037
|
+
testUnMinified(
|
|
1038
|
+
'does not detect reassignment of p5.js function (size from TypedDict or Dom) outside setup',
|
|
1039
|
+
function() {
|
|
1040
|
+
return new Promise(function(resolve) {
|
|
1041
|
+
prepSketchReaderTest(
|
|
1042
|
+
['let size = 100', 'function setup() {}'],
|
|
1043
|
+
resolve
|
|
1044
|
+
);
|
|
1045
|
+
}).then(function() {
|
|
1046
|
+
assert.strictEqual(log.length, 0);
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
);
|
|
1050
|
+
|
|
1051
|
+
testUnMinified(
|
|
1052
|
+
'detects reassignment of p5.js function (point from shape) outside setup',
|
|
1053
|
+
function() {
|
|
1054
|
+
return new Promise(function(resolve) {
|
|
1055
|
+
prepSketchReaderTest(
|
|
1056
|
+
['let point = 100', 'function setup() {}'],
|
|
1057
|
+
resolve
|
|
1058
|
+
);
|
|
1059
|
+
}).then(function() {
|
|
1060
|
+
assert.strictEqual(log.length, 1);
|
|
1061
|
+
assert.match(log[0], /you have used a p5.js reserved function/);
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
);
|
|
1065
|
+
|
|
1066
|
+
testUnMinified(
|
|
1067
|
+
'detects reassignment of p5.js functions in declaration lists',
|
|
1068
|
+
function() {
|
|
1069
|
+
return new Promise(function(resolve) {
|
|
1070
|
+
prepSketchReaderTest(
|
|
1071
|
+
['function setup() {', 'let x = 2, text = 2;', '}'],
|
|
1072
|
+
resolve
|
|
1073
|
+
);
|
|
1074
|
+
}).then(function() {
|
|
1075
|
+
assert.strictEqual(log.length, 1);
|
|
1076
|
+
assert.match(log[0], /you have used a p5.js reserved function/);
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
);
|
|
1080
|
+
|
|
1081
|
+
testUnMinified(
|
|
1082
|
+
'detects reassignment of p5.js functions in declaration lists after function calls',
|
|
1083
|
+
function() {
|
|
1084
|
+
return new Promise(function(resolve) {
|
|
1085
|
+
prepSketchReaderTest(
|
|
1086
|
+
[
|
|
1087
|
+
'function setup() {',
|
|
1088
|
+
'let x = constrain(frameCount, 0, 1000), text = 2;',
|
|
1089
|
+
'}'
|
|
1090
|
+
],
|
|
1091
|
+
resolve
|
|
1092
|
+
);
|
|
1093
|
+
}).then(function() {
|
|
1094
|
+
assert.strictEqual(log.length, 1);
|
|
1095
|
+
assert.match(log[0], /you have used a p5.js reserved function/);
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
);
|
|
1099
|
+
|
|
1100
|
+
testUnMinified(
|
|
1101
|
+
'ignores p5.js functions used in the right hand side of assignment expressions',
|
|
1102
|
+
function() {
|
|
1103
|
+
return new Promise(function(resolve) {
|
|
1104
|
+
prepSketchReaderTest(
|
|
1105
|
+
// This will still log an error, as `text` isn't being used correctly
|
|
1106
|
+
// here, but the important part is that it doesn't say that we're
|
|
1107
|
+
// trying to reassign a reserved function.
|
|
1108
|
+
['function draw() {', 'let x = constrain(100, 0, text);', '}'],
|
|
1109
|
+
resolve
|
|
1110
|
+
);
|
|
1111
|
+
}).then(function() {
|
|
1112
|
+
assert.ok(
|
|
1113
|
+
!log.some(line =>
|
|
1114
|
+
line.match(/you have used a p5.js reserved function/)
|
|
1115
|
+
)
|
|
1116
|
+
);
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
);
|
|
1120
|
+
|
|
1121
|
+
testUnMinified(
|
|
1122
|
+
'ignores p5.js function names used as function arguments',
|
|
1123
|
+
function() {
|
|
1124
|
+
return new Promise(function(resolve) {
|
|
1125
|
+
prepSketchReaderTest(
|
|
1126
|
+
['function draw() {', 'let myLog = (text) => print(text);', '}'],
|
|
1127
|
+
resolve
|
|
1128
|
+
);
|
|
1129
|
+
}).then(function() {
|
|
1130
|
+
assert.strictEqual(log.length, 0);
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
);
|
|
1134
|
+
|
|
1135
|
+
testUnMinified(
|
|
1136
|
+
'fails gracefully on inputs too complicated to parse',
|
|
1137
|
+
function() {
|
|
1138
|
+
return new Promise(function(resolve) {
|
|
1139
|
+
prepSketchReaderTest(
|
|
1140
|
+
// This technically is redefining text, but it should stop parsing
|
|
1141
|
+
// after the double nested brackets rather than try and possibly
|
|
1142
|
+
// give a false positive error. This particular assignment will get
|
|
1143
|
+
// caught at runtime regardless by
|
|
1144
|
+
// `_createFriendlyGlobalFunctionBinder`.
|
|
1145
|
+
[
|
|
1146
|
+
'function draw() {',
|
|
1147
|
+
'let x = constrain(millis(), 0, text = 100)',
|
|
1148
|
+
'}'
|
|
1149
|
+
],
|
|
1150
|
+
resolve
|
|
1151
|
+
);
|
|
1152
|
+
}).then(function() {
|
|
1153
|
+
console.log(log);
|
|
1154
|
+
assert.strictEqual(log.length, 0);
|
|
1155
|
+
});
|
|
1156
|
+
}
|
|
1157
|
+
);
|
|
1158
|
+
});
|