jspsych 7.2.1 → 7.3.0

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.
@@ -1,7 +1,7 @@
1
1
  var jsPsychModule = (function (exports) {
2
2
  'use strict';
3
3
 
4
- /*! *****************************************************************************
4
+ /******************************************************************************
5
5
  Copyright (c) Microsoft Corporation.
6
6
 
7
7
  Permission to use, copy, modify, and/or distribute this software for any
@@ -70,7 +70,7 @@ var jsPsychModule = (function (exports) {
70
70
  return self;
71
71
  };
72
72
 
73
- var version = "7.2.1";
73
+ var version = "7.3.0";
74
74
 
75
75
  class MigrationError extends Error {
76
76
  constructor(message = "The global `jsPsych` variable is no longer available in jsPsych v7.") {
@@ -842,8 +842,13 @@ var jsPsychModule = (function (exports) {
842
842
  this.img_cache = {};
843
843
  this.preloadMap = new Map();
844
844
  this.microphone_recorder = null;
845
+ this.camera_stream = null;
846
+ this.camera_recorder = null;
845
847
  }
846
848
  getVideoBuffer(videoID) {
849
+ if (videoID.startsWith("blob:")) {
850
+ this.video_buffers[videoID] = videoID;
851
+ }
847
852
  return this.video_buffers[videoID];
848
853
  }
849
854
  initAudio() {
@@ -1085,6 +1090,17 @@ var jsPsychModule = (function (exports) {
1085
1090
  getMicrophoneRecorder() {
1086
1091
  return this.microphone_recorder;
1087
1092
  }
1093
+ initializeCameraRecorder(stream, opts) {
1094
+ this.camera_stream = stream;
1095
+ const recorder = new MediaRecorder(stream, opts);
1096
+ this.camera_recorder = recorder;
1097
+ }
1098
+ getCameraStream() {
1099
+ return this.camera_stream;
1100
+ }
1101
+ getCameraRecorder() {
1102
+ return this.camera_recorder;
1103
+ }
1088
1104
  }
1089
1105
 
1090
1106
  class SimulationAPI {
@@ -1630,119 +1646,119 @@ var jsPsychModule = (function (exports) {
1630
1646
  var alea = {exports: {}};
1631
1647
 
1632
1648
  (function (module) {
1633
- // A port of an algorithm by Johannes Baagøe <baagoe@baagoe.com>, 2010
1634
- // http://baagoe.com/en/RandomMusings/javascript/
1635
- // https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
1636
- // Original work is under MIT license -
1637
-
1638
- // Copyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org>
1639
- //
1640
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1641
- // of this software and associated documentation files (the "Software"), to deal
1642
- // in the Software without restriction, including without limitation the rights
1643
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1644
- // copies of the Software, and to permit persons to whom the Software is
1645
- // furnished to do so, subject to the following conditions:
1646
- //
1647
- // The above copyright notice and this permission notice shall be included in
1648
- // all copies or substantial portions of the Software.
1649
- //
1650
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1651
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1652
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1653
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1654
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1655
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1656
- // THE SOFTWARE.
1657
-
1658
-
1659
-
1660
- (function(global, module, define) {
1661
-
1662
- function Alea(seed) {
1663
- var me = this, mash = Mash();
1664
-
1665
- me.next = function() {
1666
- var t = 2091639 * me.s0 + me.c * 2.3283064365386963e-10; // 2^-32
1667
- me.s0 = me.s1;
1668
- me.s1 = me.s2;
1669
- return me.s2 = t - (me.c = t | 0);
1670
- };
1671
-
1672
- // Apply the seeding algorithm from Baagoe.
1673
- me.c = 1;
1674
- me.s0 = mash(' ');
1675
- me.s1 = mash(' ');
1676
- me.s2 = mash(' ');
1677
- me.s0 -= mash(seed);
1678
- if (me.s0 < 0) { me.s0 += 1; }
1679
- me.s1 -= mash(seed);
1680
- if (me.s1 < 0) { me.s1 += 1; }
1681
- me.s2 -= mash(seed);
1682
- if (me.s2 < 0) { me.s2 += 1; }
1683
- mash = null;
1684
- }
1685
-
1686
- function copy(f, t) {
1687
- t.c = f.c;
1688
- t.s0 = f.s0;
1689
- t.s1 = f.s1;
1690
- t.s2 = f.s2;
1691
- return t;
1692
- }
1649
+ // A port of an algorithm by Johannes Baagøe <baagoe@baagoe.com>, 2010
1650
+ // http://baagoe.com/en/RandomMusings/javascript/
1651
+ // https://github.com/nquinlan/better-random-numbers-for-javascript-mirror
1652
+ // Original work is under MIT license -
1653
+
1654
+ // Copyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org>
1655
+ //
1656
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
1657
+ // of this software and associated documentation files (the "Software"), to deal
1658
+ // in the Software without restriction, including without limitation the rights
1659
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1660
+ // copies of the Software, and to permit persons to whom the Software is
1661
+ // furnished to do so, subject to the following conditions:
1662
+ //
1663
+ // The above copyright notice and this permission notice shall be included in
1664
+ // all copies or substantial portions of the Software.
1665
+ //
1666
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1667
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1668
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1669
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1670
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1671
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1672
+ // THE SOFTWARE.
1673
+
1674
+
1675
+
1676
+ (function(global, module, define) {
1677
+
1678
+ function Alea(seed) {
1679
+ var me = this, mash = Mash();
1680
+
1681
+ me.next = function() {
1682
+ var t = 2091639 * me.s0 + me.c * 2.3283064365386963e-10; // 2^-32
1683
+ me.s0 = me.s1;
1684
+ me.s1 = me.s2;
1685
+ return me.s2 = t - (me.c = t | 0);
1686
+ };
1687
+
1688
+ // Apply the seeding algorithm from Baagoe.
1689
+ me.c = 1;
1690
+ me.s0 = mash(' ');
1691
+ me.s1 = mash(' ');
1692
+ me.s2 = mash(' ');
1693
+ me.s0 -= mash(seed);
1694
+ if (me.s0 < 0) { me.s0 += 1; }
1695
+ me.s1 -= mash(seed);
1696
+ if (me.s1 < 0) { me.s1 += 1; }
1697
+ me.s2 -= mash(seed);
1698
+ if (me.s2 < 0) { me.s2 += 1; }
1699
+ mash = null;
1700
+ }
1693
1701
 
1694
- function impl(seed, opts) {
1695
- var xg = new Alea(seed),
1696
- state = opts && opts.state,
1697
- prng = xg.next;
1698
- prng.int32 = function() { return (xg.next() * 0x100000000) | 0; };
1699
- prng.double = function() {
1700
- return prng() + (prng() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
1701
- };
1702
- prng.quick = prng;
1703
- if (state) {
1704
- if (typeof(state) == 'object') copy(state, xg);
1705
- prng.state = function() { return copy(xg, {}); };
1706
- }
1707
- return prng;
1708
- }
1702
+ function copy(f, t) {
1703
+ t.c = f.c;
1704
+ t.s0 = f.s0;
1705
+ t.s1 = f.s1;
1706
+ t.s2 = f.s2;
1707
+ return t;
1708
+ }
1709
1709
 
1710
- function Mash() {
1711
- var n = 0xefc8249d;
1712
-
1713
- var mash = function(data) {
1714
- data = String(data);
1715
- for (var i = 0; i < data.length; i++) {
1716
- n += data.charCodeAt(i);
1717
- var h = 0.02519603282416938 * n;
1718
- n = h >>> 0;
1719
- h -= n;
1720
- h *= n;
1721
- n = h >>> 0;
1722
- h -= n;
1723
- n += h * 0x100000000; // 2^32
1724
- }
1725
- return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
1726
- };
1710
+ function impl(seed, opts) {
1711
+ var xg = new Alea(seed),
1712
+ state = opts && opts.state,
1713
+ prng = xg.next;
1714
+ prng.int32 = function() { return (xg.next() * 0x100000000) | 0; };
1715
+ prng.double = function() {
1716
+ return prng() + (prng() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
1717
+ };
1718
+ prng.quick = prng;
1719
+ if (state) {
1720
+ if (typeof(state) == 'object') copy(state, xg);
1721
+ prng.state = function() { return copy(xg, {}); };
1722
+ }
1723
+ return prng;
1724
+ }
1727
1725
 
1728
- return mash;
1729
- }
1726
+ function Mash() {
1727
+ var n = 0xefc8249d;
1728
+
1729
+ var mash = function(data) {
1730
+ data = String(data);
1731
+ for (var i = 0; i < data.length; i++) {
1732
+ n += data.charCodeAt(i);
1733
+ var h = 0.02519603282416938 * n;
1734
+ n = h >>> 0;
1735
+ h -= n;
1736
+ h *= n;
1737
+ n = h >>> 0;
1738
+ h -= n;
1739
+ n += h * 0x100000000; // 2^32
1740
+ }
1741
+ return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
1742
+ };
1743
+
1744
+ return mash;
1745
+ }
1730
1746
 
1731
1747
 
1732
- if (module && module.exports) {
1733
- module.exports = impl;
1734
- } else if (define && define.amd) {
1735
- define(function() { return impl; });
1736
- } else {
1737
- this.alea = impl;
1738
- }
1748
+ if (module && module.exports) {
1749
+ module.exports = impl;
1750
+ } else if (define && define.amd) {
1751
+ define(function() { return impl; });
1752
+ } else {
1753
+ this.alea = impl;
1754
+ }
1739
1755
 
1740
- })(
1741
- commonjsGlobal,
1742
- module, // present in node.js
1743
- (typeof undefined) == 'function' // present with an AMD loader
1744
- );
1745
- }(alea));
1756
+ })(
1757
+ commonjsGlobal,
1758
+ module, // present in node.js
1759
+ (typeof undefined) == 'function' // present with an AMD loader
1760
+ );
1761
+ } (alea));
1746
1762
 
1747
1763
  var seedrandom = alea.exports;
1748
1764
 
@@ -2409,7 +2425,11 @@ var jsPsychModule = (function (exports) {
2409
2425
  // recursive downward search for active trial to extract timeline variable
2410
2426
  timelineVariable(variable_name) {
2411
2427
  if (typeof this.timeline_parameters == "undefined") {
2412
- return this.findTimelineVariable(variable_name);
2428
+ const val = this.findTimelineVariable(variable_name);
2429
+ if (typeof val === "undefined") {
2430
+ console.warn("Timeline variable " + variable_name + " not found.");
2431
+ }
2432
+ return val;
2413
2433
  }
2414
2434
  else {
2415
2435
  // if progress.current_location is -1, then the timeline variable is being evaluated
@@ -2424,7 +2444,11 @@ var jsPsychModule = (function (exports) {
2424
2444
  loc = loc - 1;
2425
2445
  }
2426
2446
  // now find the variable
2427
- return this.timeline_parameters.timeline[loc].timelineVariable(variable_name);
2447
+ const val = this.timeline_parameters.timeline[loc].timelineVariable(variable_name);
2448
+ if (typeof val === "undefined") {
2449
+ console.warn("Timeline variable " + variable_name + " not found.");
2450
+ }
2451
+ return val;
2428
2452
  }
2429
2453
  }
2430
2454
  // recursively get all the timeline variables for this trial
@@ -2702,6 +2726,7 @@ var jsPsychModule = (function (exports) {
2702
2726
  return this.DOM_container;
2703
2727
  }
2704
2728
  finishTrial(data = {}) {
2729
+ var _a;
2705
2730
  if (this.current_trial_finished) {
2706
2731
  return;
2707
2732
  }
@@ -2714,7 +2739,7 @@ var jsPsychModule = (function (exports) {
2714
2739
  // write the data from the trial
2715
2740
  this.data.write(data);
2716
2741
  // get back the data with all of the defaults in
2717
- const trial_data = this.data.get().filter({ trial_index: this.global_trial_index });
2742
+ const trial_data = this.data.getLastTrialData();
2718
2743
  // for trial-level callbacks, we just want to pass in a reference to the values
2719
2744
  // of the DataCollection, for easy access and editing.
2720
2745
  const trial_data_values = trial_data.values()[0];
@@ -2742,46 +2767,58 @@ var jsPsychModule = (function (exports) {
2742
2767
  }
2743
2768
  }
2744
2769
  // handle extension callbacks
2745
- if (Array.isArray(current_trial.extensions)) {
2746
- for (const extension of current_trial.extensions) {
2747
- const ext_data_values = this.extensions[extension.type.info.name].on_finish(extension.params);
2748
- Object.assign(trial_data_values, ext_data_values);
2770
+ const extensionCallbackResults = ((_a = current_trial.extensions) !== null && _a !== void 0 ? _a : []).map((extension) => this.extensions[extension.type.info.name].on_finish(extension.params));
2771
+ const onExtensionCallbacksFinished = () => {
2772
+ // about to execute lots of callbacks, so switch context.
2773
+ this.internal.call_immediate = true;
2774
+ // handle callback at plugin level
2775
+ if (typeof current_trial.on_finish === "function") {
2776
+ current_trial.on_finish(trial_data_values);
2777
+ }
2778
+ // handle callback at whole-experiment level
2779
+ this.opts.on_trial_finish(trial_data_values);
2780
+ // after the above callbacks are complete, then the data should be finalized
2781
+ // for this trial. call the on_data_update handler, passing in the same
2782
+ // data object that just went through the trial's finish handlers.
2783
+ this.opts.on_data_update(trial_data_values);
2784
+ // done with callbacks
2785
+ this.internal.call_immediate = false;
2786
+ // wait for iti
2787
+ if (this.simulation_mode === "data-only") {
2788
+ this.nextTrial();
2749
2789
  }
2750
- }
2751
- // about to execute lots of callbacks, so switch context.
2752
- this.internal.call_immediate = true;
2753
- // handle callback at plugin level
2754
- if (typeof current_trial.on_finish === "function") {
2755
- current_trial.on_finish(trial_data_values);
2756
- }
2757
- // handle callback at whole-experiment level
2758
- this.opts.on_trial_finish(trial_data_values);
2759
- // after the above callbacks are complete, then the data should be finalized
2760
- // for this trial. call the on_data_update handler, passing in the same
2761
- // data object that just went through the trial's finish handlers.
2762
- this.opts.on_data_update(trial_data_values);
2763
- // done with callbacks
2764
- this.internal.call_immediate = false;
2765
- // wait for iti
2766
- if (this.simulation_mode === "data-only") {
2767
- this.nextTrial();
2768
- }
2769
- else if (typeof current_trial.post_trial_gap === null ||
2770
- typeof current_trial.post_trial_gap === "undefined") {
2771
- if (this.opts.default_iti > 0) {
2772
- setTimeout(this.nextTrial, this.opts.default_iti);
2790
+ else if (typeof current_trial.post_trial_gap === null ||
2791
+ typeof current_trial.post_trial_gap === "undefined") {
2792
+ if (this.opts.default_iti > 0) {
2793
+ setTimeout(this.nextTrial, this.opts.default_iti);
2794
+ }
2795
+ else {
2796
+ this.nextTrial();
2797
+ }
2773
2798
  }
2774
2799
  else {
2775
- this.nextTrial();
2800
+ if (current_trial.post_trial_gap > 0) {
2801
+ setTimeout(this.nextTrial, current_trial.post_trial_gap);
2802
+ }
2803
+ else {
2804
+ this.nextTrial();
2805
+ }
2776
2806
  }
2807
+ };
2808
+ // Strictly using Promise.resolve to turn all values into promises would be cleaner here, but it
2809
+ // would require user test code to make the event loop tick after every simulated key press even
2810
+ // if there are no async `on_finish` methods. Hence, in order to avoid a breaking change, we
2811
+ // only rely on the event loop if at least one `on_finish` method returns a promise.
2812
+ if (extensionCallbackResults.some((result) => typeof result.then === "function")) {
2813
+ Promise.all(extensionCallbackResults.map((result) => Promise.resolve(result).then((ext_data_values) => {
2814
+ Object.assign(trial_data_values, ext_data_values);
2815
+ }))).then(onExtensionCallbacksFinished);
2777
2816
  }
2778
2817
  else {
2779
- if (current_trial.post_trial_gap > 0) {
2780
- setTimeout(this.nextTrial, current_trial.post_trial_gap);
2781
- }
2782
- else {
2783
- this.nextTrial();
2818
+ for (const values of extensionCallbackResults) {
2819
+ Object.assign(trial_data_values, values);
2784
2820
  }
2821
+ onExtensionCallbacksFinished();
2785
2822
  }
2786
2823
  }
2787
2824
  endExperiment(end_message = "", data = {}) {
@@ -3069,16 +3106,16 @@ var jsPsychModule = (function (exports) {
3069
3106
  }
3070
3107
  evaluateTimelineVariables(trial) {
3071
3108
  for (const key of Object.keys(trial)) {
3072
- // timeline variables on the root level
3073
3109
  if (typeof trial[key] === "object" &&
3074
3110
  trial[key] !== null &&
3075
3111
  typeof trial[key].timelineVariablePlaceholder !== "undefined") {
3076
- /*trial[key].toString().replace(/\s/g, "") ==
3077
- "function(){returntimeline.timelineVariable(varname);}"
3078
- )*/ trial[key] = trial[key].timelineVariableFunction();
3112
+ trial[key] = trial[key].timelineVariableFunction();
3079
3113
  }
3080
3114
  // timeline variables that are nested in objects
3081
- if (typeof trial[key] === "object" && trial[key] !== null) {
3115
+ if (typeof trial[key] === "object" &&
3116
+ trial[key] !== null &&
3117
+ key !== "timeline" &&
3118
+ key !== "timeline_variables") {
3082
3119
  this.evaluateTimelineVariables(trial[key]);
3083
3120
  }
3084
3121
  }
@@ -3121,9 +3158,11 @@ var jsPsychModule = (function (exports) {
3121
3158
  else if (typeof obj === "object") {
3122
3159
  if (info === null || !info.nested) {
3123
3160
  for (const key of Object.keys(obj)) {
3124
- if (key === "type") {
3161
+ if (key === "type" || key === "timeline" || key === "timeline_variables") {
3125
3162
  // Ignore the object's `type` field because it contains a plugin and we do not want to
3126
- // call plugin functions
3163
+ // call plugin functions. Also ignore `timeline` and `timeline_variables` because they
3164
+ // are used in the `trials` parameter of the preload plugin and we don't want to actually
3165
+ // evaluate those in that context.
3127
3166
  continue;
3128
3167
  }
3129
3168
  obj[key] = this.replaceFunctionsWithValues(obj[key], null);
@@ -3253,6 +3292,7 @@ var jsPsychModule = (function (exports) {
3253
3292
  }
3254
3293
  }
3255
3294
 
3295
+ // __rollup-babel-import-regenerator-runtime__
3256
3296
  // temporary patch for Safari
3257
3297
  if (typeof window !== "undefined" &&
3258
3298
  window.hasOwnProperty("webkitAudioContext") &&