From 116ddb8933418b490339e65ebbd1240b7b648eba Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Mon, 20 Sep 2021 13:51:38 +0800 Subject: [PATCH 1/3] MDL-72609 behat: Rewrite core/pending to observe ES6 style This commit makes the following changes: * convert to use ES6 module format * migrate from a jQuery Deferred to a native ES6 promise * add a native-Promise-like instantiation New uses are documented in appropriate jsdoc with examples. --- lib/amd/build/pending.min.js | 17 ++--- lib/amd/build/pending.min.js.map | 2 +- lib/amd/src/pending.js | 118 +++++++++++++++++++++++++------ 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/lib/amd/build/pending.min.js b/lib/amd/build/pending.min.js index e4db8929c4e..a159467905d 100644 --- a/lib/amd/build/pending.min.js +++ b/lib/amd/build/pending.min.js @@ -1,11 +1,12 @@ +define("core/pending",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default= /** - * A helper to manage pendingJS checks. - * - * @module core/pending - * @copyright 2018 Andrew Nicols - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 3.6 - */ -define("core/pending",["jquery"],(function($){var request=function(pendingKey){var pendingPromise=$.Deferred();return pendingKey=pendingKey||{},M.util.js_pending(pendingKey),pendingPromise.then((function(){return M.util.js_complete(pendingKey)})).catch(),pendingPromise};return request.prototype.constructor=request,request})); + * A helper used to inform Behat that an operation is in progress and that Behat must wait for it to complete. + * + * @module core/pending + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 3.6 + */ +class{static request(pendingKey){return window.console.error("The core/pending::request method has been deprecated. "+"Please use one of the alternative calls to core/pending, for example \"new Pending('".concat(pendingKey,"')\". ")+"Called with ".concat(pendingKey)),new this(pendingKey)}constructor(){let resolver,rejector,pendingKey=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"pendingPromise";const pendingPromise=this.constructor.Promise(((resolve,reject)=>{resolver=resolve,rejector=reject}),pendingKey);return pendingPromise.resolve=resolver,pendingPromise.reject=rejector,pendingPromise}static Promise(fn){let pendingKey=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"pendingPromise";const resolver=new Promise(((resolve,reject)=>{M.util.js_pending(pendingKey),fn(resolve,reject)}));return resolver.then((()=>{M.util.js_complete(pendingKey)})).catch(),resolver}},_exports.default})); //# sourceMappingURL=pending.min.js.map \ No newline at end of file diff --git a/lib/amd/build/pending.min.js.map b/lib/amd/build/pending.min.js.map index 7a39ab0eec7..c73b363a405 100644 --- a/lib/amd/build/pending.min.js.map +++ b/lib/amd/build/pending.min.js.map @@ -1 +1 @@ -{"version":3,"file":"pending.min.js","sources":["../src/pending.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A helper to manage pendingJS checks.\n *\n * @module core/pending\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.6\n */\ndefine(['jquery'], function($) {\n\n /**\n * Request a new pendingPromise to be resolved.\n *\n * When the action you are performing is complete, simply call resolve on the returned Promise.\n *\n * @param {Object} pendingKey An optional key value to use\n * @return {Promise}\n */\n var request = function(pendingKey) {\n var pendingPromise = $.Deferred();\n\n pendingKey = pendingKey || {};\n M.util.js_pending(pendingKey);\n\n pendingPromise.then(function() {\n return M.util.js_complete(pendingKey);\n })\n .catch();\n\n return pendingPromise;\n };\n\n request.prototype.constructor = request;\n\n return request;\n});\n"],"names":["define","$","request","pendingKey","pendingPromise","Deferred","M","util","js_pending","then","js_complete","catch","prototype","constructor"],"mappings":";;;;;;;;AAuBAA,sBAAO,CAAC,WAAW,SAASC,OAUpBC,QAAU,SAASC,gBACfC,eAAiBH,EAAEI,kBAEvBF,WAAaA,YAAc,GAC3BG,EAAEC,KAAKC,WAAWL,YAElBC,eAAeK,MAAK,kBACTH,EAAEC,KAAKG,YAAYP,eAE7BQ,QAEMP,uBAGXF,QAAQU,UAAUC,YAAcX,QAEzBA"} \ No newline at end of file +{"version":3,"file":"pending.min.js","sources":["../src/pending.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A helper used to inform Behat that an operation is in progress and that Behat must wait for it to complete.\n *\n * @module core/pending\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.6\n */\n\n/**\n * A helper used to register any long-running operations that are in-progress and that Behat must wait for it to complete.\n *\n * This is useful in cases where the user interface may be updated and take some time to change - for example where\n * applying a transition.\n *\n * This data is used by Behat, but may also be consumed by other location too.\n *\n * By informing Behat that an action is about to happen, and then that it is complete, allows\n * Behat to wait for that completion and avoid random failures in automated testing.\n *\n * Note: It is recommended that a descriptive key be used to aid in debugging where possible, but this is optional.\n */\nexport default class {\n\n /**\n * Create a new Pending Promise statically.\n *\n * @param {String} pendingKey An identifier to help in debugging\n * @return {Promise} A Native Promise\n * @deprecated since Moodle 4.2\n */\n static request(pendingKey) {\n window.console.error(\n `The core/pending::request method has been deprecated. ` +\n `Please use one of the alternative calls to core/pending, for example \"new Pending('${pendingKey}')\". ` +\n `Called with ${pendingKey}`\n );\n return new this(pendingKey);\n }\n\n /**\n * Request a new pendingPromise for later resolution.\n *\n * When the action you are performing is complete, simply call resolve on the returned Promise.\n *\n * @param {String} [pendingKey='pendingPromise'] An identifier to help in debugging\n * @return {Promise} A Native Promise\n * @example\n * import Pending from 'core/pending';\n * import {get_string as getString} from 'core/str';\n *\n * const stringPromise = new Pending('mod_myexample/setup');\n * const myString = getString('ok')\n * .then(okay => {\n * window.console.log(okay);\n * })\n * .then(okay => stringPromise.resolve(okay));\n */\n constructor(pendingKey = 'pendingPromise') {\n let resolver;\n let rejector;\n const pendingPromise = this.constructor.Promise((resolve, reject) => {\n resolver = resolve;\n rejector = reject;\n }, pendingKey);\n pendingPromise.resolve = resolver;\n pendingPromise.reject = rejector;\n\n return pendingPromise;\n }\n\n /**\n * Create a new Pending Promise with the same interface as a native Promise.\n *\n * @param {Callable} fn A callable which takes the resolve and reject arguments as in a Native Promise constructor.\n * @param {String} [pendingKey='pendingPromise'] An identifier to help in debugging\n * @returns {Promise}\n * @since Moodle 4.2\n * @example\n * // Use the Pending class in the same way that you would a Native Promise.\n * import Pending from 'core/pending';\n * import {get_string as getString} from 'core/str';\n *\n * export const init => {\n * Pending.Promise((resolve, reject) => {\n * getString('ok')\n * .then(okay => {\n * window.console.log(okay);\n * return okay;\n * })\n * .then(resolve)\n * .catch(reject);\n * }, 'mod_myexample/setup:init');\n * };\n */\n static Promise(fn, pendingKey = 'pendingPromise') {\n const resolver = new Promise((resolve, reject) => {\n M.util.js_pending(pendingKey);\n\n fn(resolve, reject);\n });\n\n resolver.then(() => {\n M.util.js_complete(pendingKey);\n return;\n }).catch();\n\n return resolver;\n }\n}\n"],"names":["pendingKey","window","console","error","this","constructor","resolver","rejector","pendingPromise","Promise","resolve","reject","fn","M","util","js_pending","then","js_complete","catch"],"mappings":";;;;;;;;;qBA8CmBA,mBACXC,OAAOC,QAAQC,MACX,uJACsFH,2CACvEA,aAEZ,IAAII,KAAKJ,YAqBpBK,kBACQC,SACAC,SAFIP,kEAAa,uBAGfQ,eAAiBJ,KAAKC,YAAYI,SAAQ,CAACC,QAASC,UACtDL,SAAWI,QACXH,SAAWI,SACZX,mBACHQ,eAAeE,QAAUJ,SACzBE,eAAeG,OAASJ,SAEjBC,8BA2BII,QAAIZ,kEAAa,uBACtBM,SAAW,IAAIG,SAAQ,CAACC,QAASC,UACnCE,EAAEC,KAAKC,WAAWf,YAElBY,GAAGF,QAASC,kBAGhBL,SAASU,MAAK,KACVH,EAAEC,KAAKG,YAAYjB,eAEpBkB,QAEIZ"} \ No newline at end of file diff --git a/lib/amd/src/pending.js b/lib/amd/src/pending.js index 221fd3f799d..059256a1a4e 100644 --- a/lib/amd/src/pending.js +++ b/lib/amd/src/pending.js @@ -14,38 +14,112 @@ // along with Moodle. If not, see . /** - * A helper to manage pendingJS checks. + * A helper used to inform Behat that an operation is in progress and that Behat must wait for it to complete. * * @module core/pending * @copyright 2018 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since 3.6 */ -define(['jquery'], function($) { - /** - * Request a new pendingPromise to be resolved. - * - * When the action you are performing is complete, simply call resolve on the returned Promise. - * - * @param {Object} pendingKey An optional key value to use - * @return {Promise} - */ - var request = function(pendingKey) { - var pendingPromise = $.Deferred(); +/** + * A helper used to register any long-running operations that are in-progress and that Behat must wait for it to complete. + * + * This is useful in cases where the user interface may be updated and take some time to change - for example where + * applying a transition. + * + * This data is used by Behat, but may also be consumed by other location too. + * + * By informing Behat that an action is about to happen, and then that it is complete, allows + * Behat to wait for that completion and avoid random failures in automated testing. + * + * Note: It is recommended that a descriptive key be used to aid in debugging where possible, but this is optional. + */ +export default class { - pendingKey = pendingKey || {}; - M.util.js_pending(pendingKey); + /** + * Create a new Pending Promise statically. + * + * @param {String} pendingKey An identifier to help in debugging + * @return {Promise} A Native Promise + * @deprecated since Moodle 4.2 + */ + static request(pendingKey) { + window.console.error( + `The core/pending::request method has been deprecated. ` + + `Please use one of the alternative calls to core/pending, for example "new Pending('${pendingKey}')". ` + + `Called with ${pendingKey}` + ); + return new this(pendingKey); + } - pendingPromise.then(function() { - return M.util.js_complete(pendingKey); - }) - .catch(); + /** + * Request a new pendingPromise for later resolution. + * + * When the action you are performing is complete, simply call resolve on the returned Promise. + * + * @param {String} [pendingKey='pendingPromise'] An identifier to help in debugging + * @return {Promise} A Native Promise + * @example + * import Pending from 'core/pending'; + * import {get_string as getString} from 'core/str'; + * + * const stringPromise = new Pending('mod_myexample/setup'); + * const myString = getString('ok') + * .then(okay => { + * window.console.log(okay); + * }) + * .then(okay => stringPromise.resolve(okay)); + */ + constructor(pendingKey = 'pendingPromise') { + let resolver; + let rejector; + const pendingPromise = this.constructor.Promise((resolve, reject) => { + resolver = resolve; + rejector = reject; + }, pendingKey); + pendingPromise.resolve = resolver; + pendingPromise.reject = rejector; return pendingPromise; - }; + } - request.prototype.constructor = request; + /** + * Create a new Pending Promise with the same interface as a native Promise. + * + * @param {Callable} fn A callable which takes the resolve and reject arguments as in a Native Promise constructor. + * @param {String} [pendingKey='pendingPromise'] An identifier to help in debugging + * @returns {Promise} + * @since Moodle 4.2 + * @example + * // Use the Pending class in the same way that you would a Native Promise. + * import Pending from 'core/pending'; + * import {get_string as getString} from 'core/str'; + * + * export const init => { + * Pending.Promise((resolve, reject) => { + * getString('ok') + * .then(okay => { + * window.console.log(okay); + * return okay; + * }) + * .then(resolve) + * .catch(reject); + * }, 'mod_myexample/setup:init'); + * }; + */ + static Promise(fn, pendingKey = 'pendingPromise') { + const resolver = new Promise((resolve, reject) => { + M.util.js_pending(pendingKey); - return request; -}); + fn(resolve, reject); + }); + + resolver.then(() => { + M.util.js_complete(pendingKey); + return; + }).catch(); + + return resolver; + } +} From b8f6b7602bc7d3fb09d53e50135bbe3b8fd02a44 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 8 Feb 2022 12:35:17 +0800 Subject: [PATCH 2/3] MDL-72609 core: Fix complete_js to be a list of strings --- lib/javascript-static.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/javascript-static.js b/lib/javascript-static.js index 94216ace27f..ef41865c84f 100644 --- a/lib/javascript-static.js +++ b/lib/javascript-static.js @@ -708,7 +708,7 @@ M.util.js_complete = function(uniqid) { // the native function. Y.Array polyfills the native function if it does not exist. var index = Y.Array.indexOf(M.util.pending_js, uniqid); if (index >= 0) { - M.util.complete_js.push(M.util.pending_js.splice(index, 1)); + M.util.complete_js.push(M.util.pending_js.splice(index, 1)[0]); } else { window.console.log("Unable to locate key for js_complete call", uniqid); } From fcad49b03b07a78e612cabedabe38c6b0b248d42 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Mon, 23 Jan 2023 14:58:11 +0800 Subject: [PATCH 3/3] MDL-72609 core: Remove YUI from M.util.pendingJS --- lib/javascript-static.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/javascript-static.js b/lib/javascript-static.js index ef41865c84f..92150820e54 100644 --- a/lib/javascript-static.js +++ b/lib/javascript-static.js @@ -704,9 +704,7 @@ YUI.add('moodle-core-io', function(Y) { * @return {Number} Number of pending items remaining after removing this item */ M.util.js_complete = function(uniqid) { - // Use the Y.Array.indexOf instead of the native because some older browsers do not support - // the native function. Y.Array polyfills the native function if it does not exist. - var index = Y.Array.indexOf(M.util.pending_js, uniqid); + const index = M.util.pending_js.indexOf(uniqid); if (index >= 0) { M.util.complete_js.push(M.util.pending_js.splice(index, 1)[0]); } else {