Replace XMLHttpRequest (#562)
* Replace XMLHttpRequest with fetch * Implement fetch placeholder for tests
This commit is contained in:
parent
5cba421201
commit
8a7ff6a18c
@ -82,16 +82,24 @@ class AudioUriBuilder {
|
||||
}
|
||||
|
||||
async _getUriJpod101Alternate(definition) {
|
||||
const response = await new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
|
||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
||||
xhr.send(`post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}`);
|
||||
const fetchUrl = 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post';
|
||||
const data = `post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}`;
|
||||
const response = await fetch(fetchUrl, {
|
||||
method: 'POST',
|
||||
mode: 'no-cors',
|
||||
cache: 'default',
|
||||
credentials: 'omit',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: data
|
||||
});
|
||||
const responseText = await response.text();
|
||||
console.log(responseText);
|
||||
|
||||
const dom = new DOMParser().parseFromString(response, 'text/html');
|
||||
const dom = new DOMParser().parseFromString(responseText, 'text/html');
|
||||
for (const row of dom.getElementsByClassName('dc-result-row')) {
|
||||
try {
|
||||
const url = row.querySelector('audio>source[src]').getAttribute('src');
|
||||
@ -108,15 +116,18 @@ class AudioUriBuilder {
|
||||
}
|
||||
|
||||
async _getUriJisho(definition) {
|
||||
const response = await new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', `https://jisho.org/search/${definition.expression}`);
|
||||
xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
|
||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
||||
xhr.send();
|
||||
const fetchUrl = `https://jisho.org/search/${definition.expression}`;
|
||||
const response = await fetch(fetchUrl, {
|
||||
method: 'GET',
|
||||
mode: 'no-cors',
|
||||
cache: 'default',
|
||||
credentials: 'omit',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer'
|
||||
});
|
||||
const responseText = await response.text();
|
||||
|
||||
const dom = new DOMParser().parseFromString(response, 'text/html');
|
||||
const dom = new DOMParser().parseFromString(responseText, 'text/html');
|
||||
try {
|
||||
const audio = dom.getElementById(`audio_${definition.expression}:${definition.reading}`);
|
||||
if (audio !== null) {
|
||||
|
@ -16,28 +16,28 @@
|
||||
*/
|
||||
|
||||
|
||||
function requestText(url, action, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.overrideMimeType('text/plain');
|
||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
||||
xhr.addEventListener('error', () => reject(new Error('Failed to connect')));
|
||||
xhr.open(action, url);
|
||||
if (params) {
|
||||
xhr.send(JSON.stringify(params));
|
||||
} else {
|
||||
xhr.send();
|
||||
}
|
||||
async function requestText(url, method, data) {
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
mode: 'no-cors',
|
||||
cache: 'default',
|
||||
credentials: 'omit',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
body: (data ? JSON.stringify(data) : void 0)
|
||||
});
|
||||
return await response.text();
|
||||
}
|
||||
|
||||
async function requestJson(url, action, params) {
|
||||
const responseText = await requestText(url, action, params);
|
||||
try {
|
||||
return JSON.parse(responseText);
|
||||
} catch (e) {
|
||||
const error = new Error(`Invalid response (${e.message || e})`);
|
||||
error.data = {url, action, params, responseText};
|
||||
throw error;
|
||||
}
|
||||
async function requestJson(url, method, data) {
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
mode: 'no-cors',
|
||||
cache: 'default',
|
||||
credentials: 'omit',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
body: (data ? JSON.stringify(data) : void 0)
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
|
@ -169,22 +169,22 @@ class AudioSystem {
|
||||
});
|
||||
}
|
||||
|
||||
_createAudioBinaryFromUrl(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.addEventListener('load', async () => {
|
||||
const arrayBuffer = xhr.response;
|
||||
if (!await this._isAudioBinaryValid(arrayBuffer)) {
|
||||
reject(new Error('Could not retrieve audio'));
|
||||
} else {
|
||||
resolve(arrayBuffer);
|
||||
}
|
||||
});
|
||||
xhr.addEventListener('error', () => reject(new Error('Failed to connect')));
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
async _createAudioBinaryFromUrl(url) {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
mode: 'no-cors',
|
||||
cache: 'default',
|
||||
credentials: 'omit',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer'
|
||||
});
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
|
||||
if (!await this._isAudioBinaryValid(arrayBuffer)) {
|
||||
throw new Error('Could not retrieve audio');
|
||||
}
|
||||
|
||||
return arrayBuffer;
|
||||
}
|
||||
|
||||
_isAudioValid(audio) {
|
||||
|
@ -38,60 +38,6 @@ const chrome = {
|
||||
}
|
||||
};
|
||||
|
||||
class XMLHttpRequest {
|
||||
constructor() {
|
||||
this._eventCallbacks = new Map();
|
||||
this._url = '';
|
||||
this._responseText = null;
|
||||
}
|
||||
|
||||
overrideMimeType() {
|
||||
// NOP
|
||||
}
|
||||
|
||||
addEventListener(eventName, callback) {
|
||||
let callbacks = this._eventCallbacks.get(eventName);
|
||||
if (typeof callbacks === 'undefined') {
|
||||
callbacks = [];
|
||||
this._eventCallbacks.set(eventName, callbacks);
|
||||
}
|
||||
callbacks.push(callback);
|
||||
}
|
||||
|
||||
open(action, url2) {
|
||||
this._url = url2;
|
||||
}
|
||||
|
||||
send() {
|
||||
const filePath = url.fileURLToPath(this._url);
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
let source;
|
||||
try {
|
||||
source = fs.readFileSync(filePath, {encoding: 'utf8'});
|
||||
} catch (e) {
|
||||
this._trigger('error');
|
||||
return;
|
||||
}
|
||||
this._responseText = source;
|
||||
this._trigger('load');
|
||||
});
|
||||
}
|
||||
|
||||
get responseText() {
|
||||
return this._responseText;
|
||||
}
|
||||
|
||||
_trigger(eventName, ...args) {
|
||||
const callbacks = this._eventCallbacks.get(eventName);
|
||||
if (typeof callbacks === 'undefined') { return; }
|
||||
|
||||
for (let i = 0, ii = callbacks.length; i < ii; ++i) {
|
||||
callbacks[i](...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Image {
|
||||
constructor() {
|
||||
this._src = '';
|
||||
@ -138,11 +84,21 @@ class Image {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetch(url2) {
|
||||
const filePath = url.fileURLToPath(url2);
|
||||
await Promise.resolve();
|
||||
const content = fs.readFileSync(filePath, {encoding: null});
|
||||
return {
|
||||
text: async () => Promise.resolve(content.toString('utf8')),
|
||||
json: async () => Promise.resolve(JSON.parse(content.toString('utf8')))
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const vm = new VM({
|
||||
chrome,
|
||||
Image,
|
||||
XMLHttpRequest,
|
||||
fetch,
|
||||
indexedDB: global.indexedDB,
|
||||
IDBKeyRange: global.IDBKeyRange,
|
||||
JSZip: yomichanTest.JSZip,
|
||||
|
Loading…
Reference in New Issue
Block a user