Spaces:
Runtime error
Runtime error
| /** | |
| * @fileoverview | |
| * Many ScratchX extensions require jQuery to do things like loading scripts and making requests. | |
| * The real jQuery is pretty large and we'd rather not bring in everything, so this file reimplements | |
| * small stubs of a few jQuery methods. | |
| * It's just supposed to be enough to make existing ScratchX extensions work, nothing more. | |
| */ | |
| const log = require('../util/log'); | |
| const jQuery = () => { | |
| throw new Error('Not implemented'); | |
| }; | |
| jQuery.getScript = (src, callback) => { | |
| const script = document.createElement('script'); | |
| script.src = src; | |
| if (callback) { | |
| // We don't implement callback arguments. | |
| script.onload = () => callback(); | |
| } | |
| document.body.appendChild(script); | |
| }; | |
| /** | |
| * @param {Record<string, any>|undefined} obj | |
| * @returns {URLSearchParams} | |
| */ | |
| const objectToQueryString = obj => { | |
| const params = new URLSearchParams(); | |
| if (obj) { | |
| for (const key of Object.keys(obj)) { | |
| params.set(key, obj[key]); | |
| } | |
| } | |
| return params; | |
| }; | |
| let jsonpCallback = 0; | |
| jQuery.ajax = async (arg1, arg2) => { | |
| let options = {}; | |
| if (arg1 && arg2) { | |
| options = arg2; | |
| options.url = arg1; | |
| } else if (arg1) { | |
| options = arg1; | |
| } | |
| const urlParameters = objectToQueryString(options.data); | |
| const getFinalURL = () => { | |
| const query = urlParameters.toString(); | |
| let url = options.url; | |
| if (query) { | |
| url += `?${query}`; | |
| } | |
| // Forcibly upgrade all HTTP requests to HTTPS so that they don't error on HTTPS sites | |
| // All the extensions we care about work fine with this | |
| if (url.startsWith('http://')) { | |
| url = url.replace('http://', 'https://'); | |
| } | |
| return url; | |
| }; | |
| const successCallback = result => { | |
| if (options.success) { | |
| options.success(result); | |
| } | |
| }; | |
| const errorCallback = error => { | |
| log.error(error); | |
| if (options.error) { | |
| // The error object we provide here might not match what jQuery provides but it's enough to | |
| // prevent extensions from throwing errors trying to access properties. | |
| options.error(error); | |
| } | |
| }; | |
| try { | |
| if (options.dataType === 'jsonp') { | |
| const callbackName = `_jsonp_callback${jsonpCallback++}`; | |
| global[callbackName] = data => { | |
| delete global[callbackName]; | |
| successCallback(data); | |
| }; | |
| const callbackParameterName = options.jsonp || 'callback'; | |
| urlParameters.set(callbackParameterName, callbackName); | |
| jQuery.getScript(getFinalURL()); | |
| return; | |
| } | |
| if (options.dataType === 'script') { | |
| jQuery.getScript(getFinalURL(), successCallback); | |
| return; | |
| } | |
| const res = await fetch(getFinalURL(), { | |
| headers: options.headers | |
| }); | |
| // dataType defaults to "Intelligent Guess (xml, json, script, or html)" | |
| // It happens that all the ScratchX extensions we care about either set dataType to "json" or | |
| // leave it blank and implicitly request JSON, so this works good enough for now. | |
| successCallback(await res.json()); | |
| } catch (e) { | |
| errorCallback(e); | |
| } | |
| }; | |
| module.exports = jQuery; | |