q5 2.10.6 → 2.10.8

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.
Files changed (72) hide show
  1. package/deno.json +35 -0
  2. package/package.json +3 -6
  3. package/q5-deno-server.js +38 -0
  4. package/q5-server.js +3 -3
  5. package/q5.js +20 -11
  6. package/q5.min.js +1 -1
  7. package/src/q5-2d-drawing.js +2 -2
  8. package/src/q5-canvas.js +14 -8
  9. package/src/q5-input.js +1 -1
  10. package/src/q5-webgpu-canvas.js +3 -0
  11. package/test/core.test.js +33 -0
  12. package/test/readme.md +5 -0
  13. package/.vscode/launch.json +0 -26
  14. package/.vscode/settings.json +0 -3
  15. package/bun.lockb +0 -0
  16. package/p5-tests/js/chai_helpers.js +0 -20
  17. package/p5-tests/js/mocha_setup.js +0 -2
  18. package/p5-tests/js/modernizr.js +0 -5
  19. package/p5-tests/js/p5_helpers.js +0 -135
  20. package/p5-tests/js/sinon.js +0 -5949
  21. package/p5-tests/mocha.css +0 -289
  22. package/p5-tests/test.html +0 -71
  23. package/p5-tests/unit/color/color_conversion.js +0 -68
  24. package/p5-tests/unit/color/creating_reading.js +0 -217
  25. package/p5-tests/unit/color/p5.Color.js +0 -1000
  26. package/p5-tests/unit/color/setting.js +0 -289
  27. package/p5-tests/unit/core/2d_primitives.js +0 -490
  28. package/p5-tests/unit/core/attributes.js +0 -115
  29. package/p5-tests/unit/core/curves.js +0 -139
  30. package/p5-tests/unit/core/environment.js +0 -248
  31. package/p5-tests/unit/core/error_helpers.js +0 -1158
  32. package/p5-tests/unit/core/main.js +0 -340
  33. package/p5-tests/unit/core/p5.Element.js +0 -773
  34. package/p5-tests/unit/core/p5.Graphics.js +0 -179
  35. package/p5-tests/unit/core/preload.js +0 -285
  36. package/p5-tests/unit/core/rendering.js +0 -116
  37. package/p5-tests/unit/core/structure.js +0 -293
  38. package/p5-tests/unit/core/transform.js +0 -144
  39. package/p5-tests/unit/core/version.js +0 -28
  40. package/p5-tests/unit/core/vertex.js +0 -137
  41. package/p5-tests/unit/dom/dom.js +0 -2146
  42. package/p5-tests/unit/events/acceleration.js +0 -213
  43. package/p5-tests/unit/events/keyboard.js +0 -179
  44. package/p5-tests/unit/events/mouse.js +0 -487
  45. package/p5-tests/unit/events/touch.js +0 -180
  46. package/p5-tests/unit/image/downloading.js +0 -379
  47. package/p5-tests/unit/image/filters.js +0 -92
  48. package/p5-tests/unit/image/loading.js +0 -413
  49. package/p5-tests/unit/image/p5.Image.js +0 -201
  50. package/p5-tests/unit/image/pixels.js +0 -234
  51. package/p5-tests/unit/io/files.js +0 -378
  52. package/p5-tests/unit/io/loadBytes.js +0 -149
  53. package/p5-tests/unit/io/loadImage.js +0 -123
  54. package/p5-tests/unit/io/loadJSON.js +0 -185
  55. package/p5-tests/unit/io/loadModel.js +0 -215
  56. package/p5-tests/unit/io/loadShader.js +0 -176
  57. package/p5-tests/unit/io/loadStrings.js +0 -140
  58. package/p5-tests/unit/io/loadTable.js +0 -183
  59. package/p5-tests/unit/io/loadXML.js +0 -127
  60. package/p5-tests/unit/io/saveModel.js +0 -113
  61. package/p5-tests/unit/io/saveTable.js +0 -142
  62. package/p5-tests/unit/math/calculation.js +0 -452
  63. package/p5-tests/unit/math/noise.js +0 -66
  64. package/p5-tests/unit/math/p5.Vector.js +0 -1886
  65. package/p5-tests/unit/math/random.js +0 -177
  66. package/p5-tests/unit/math/trigonometry.js +0 -144
  67. package/p5-tests/unit/spec.js +0 -50
  68. package/p5-tests/unit/typography/attributes.js +0 -120
  69. package/p5-tests/unit/typography/loadFont.js +0 -162
  70. package/p5-tests/unit/typography/p5.Font.js +0 -63
  71. package/p5-tests/unit/utilities/conversion.js +0 -329
  72. package/p5-tests/unit/utilities/time_date.js +0 -133
@@ -1,1158 +0,0 @@
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
- });