soiz1's picture
Upload 811 files
30c32c8 verified
raw
history blame
3.36 kB
/**
* @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;