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) {
|
async _getUriJpod101Alternate(definition) {
|
||||||
const response = await new Promise((resolve, reject) => {
|
const fetchUrl = 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post';
|
||||||
const xhr = new XMLHttpRequest();
|
const data = `post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}`;
|
||||||
xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
|
const response = await fetch(fetchUrl, {
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
method: 'POST',
|
||||||
xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
|
mode: 'no-cors',
|
||||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
cache: 'default',
|
||||||
xhr.send(`post=dictionary_reference&match_type=exact&search_query=${encodeURIComponent(definition.expression)}`);
|
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')) {
|
for (const row of dom.getElementsByClassName('dc-result-row')) {
|
||||||
try {
|
try {
|
||||||
const url = row.querySelector('audio>source[src]').getAttribute('src');
|
const url = row.querySelector('audio>source[src]').getAttribute('src');
|
||||||
@ -108,15 +116,18 @@ class AudioUriBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _getUriJisho(definition) {
|
async _getUriJisho(definition) {
|
||||||
const response = await new Promise((resolve, reject) => {
|
const fetchUrl = `https://jisho.org/search/${definition.expression}`;
|
||||||
const xhr = new XMLHttpRequest();
|
const response = await fetch(fetchUrl, {
|
||||||
xhr.open('GET', `https://jisho.org/search/${definition.expression}`);
|
method: 'GET',
|
||||||
xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data')));
|
mode: 'no-cors',
|
||||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
cache: 'default',
|
||||||
xhr.send();
|
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 {
|
try {
|
||||||
const audio = dom.getElementById(`audio_${definition.expression}:${definition.reading}`);
|
const audio = dom.getElementById(`audio_${definition.expression}:${definition.reading}`);
|
||||||
if (audio !== null) {
|
if (audio !== null) {
|
||||||
|
@ -16,28 +16,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
function requestText(url, action, params) {
|
async function requestText(url, method, data) {
|
||||||
return new Promise((resolve, reject) => {
|
const response = await fetch(url, {
|
||||||
const xhr = new XMLHttpRequest();
|
method,
|
||||||
xhr.overrideMimeType('text/plain');
|
mode: 'no-cors',
|
||||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
cache: 'default',
|
||||||
xhr.addEventListener('error', () => reject(new Error('Failed to connect')));
|
credentials: 'omit',
|
||||||
xhr.open(action, url);
|
redirect: 'follow',
|
||||||
if (params) {
|
referrerPolicy: 'no-referrer',
|
||||||
xhr.send(JSON.stringify(params));
|
body: (data ? JSON.stringify(data) : void 0)
|
||||||
} else {
|
|
||||||
xhr.send();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
return await response.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function requestJson(url, action, params) {
|
async function requestJson(url, method, data) {
|
||||||
const responseText = await requestText(url, action, params);
|
const response = await fetch(url, {
|
||||||
try {
|
method,
|
||||||
return JSON.parse(responseText);
|
mode: 'no-cors',
|
||||||
} catch (e) {
|
cache: 'default',
|
||||||
const error = new Error(`Invalid response (${e.message || e})`);
|
credentials: 'omit',
|
||||||
error.data = {url, action, params, responseText};
|
redirect: 'follow',
|
||||||
throw error;
|
referrerPolicy: 'no-referrer',
|
||||||
}
|
body: (data ? JSON.stringify(data) : void 0)
|
||||||
|
});
|
||||||
|
return await response.json();
|
||||||
}
|
}
|
||||||
|
@ -169,22 +169,22 @@ class AudioSystem {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_createAudioBinaryFromUrl(url) {
|
async _createAudioBinaryFromUrl(url) {
|
||||||
return new Promise((resolve, reject) => {
|
const response = await fetch(url, {
|
||||||
const xhr = new XMLHttpRequest();
|
method: 'GET',
|
||||||
xhr.responseType = 'arraybuffer';
|
mode: 'no-cors',
|
||||||
xhr.addEventListener('load', async () => {
|
cache: 'default',
|
||||||
const arrayBuffer = xhr.response;
|
credentials: 'omit',
|
||||||
if (!await this._isAudioBinaryValid(arrayBuffer)) {
|
redirect: 'follow',
|
||||||
reject(new Error('Could not retrieve audio'));
|
referrerPolicy: 'no-referrer'
|
||||||
} else {
|
|
||||||
resolve(arrayBuffer);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
xhr.addEventListener('error', () => reject(new Error('Failed to connect')));
|
|
||||||
xhr.open('GET', url);
|
|
||||||
xhr.send();
|
|
||||||
});
|
});
|
||||||
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
|
||||||
|
if (!await this._isAudioBinaryValid(arrayBuffer)) {
|
||||||
|
throw new Error('Could not retrieve audio');
|
||||||
|
}
|
||||||
|
|
||||||
|
return arrayBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isAudioValid(audio) {
|
_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 {
|
class Image {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._src = '';
|
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({
|
const vm = new VM({
|
||||||
chrome,
|
chrome,
|
||||||
Image,
|
Image,
|
||||||
XMLHttpRequest,
|
fetch,
|
||||||
indexedDB: global.indexedDB,
|
indexedDB: global.indexedDB,
|
||||||
IDBKeyRange: global.IDBKeyRange,
|
IDBKeyRange: global.IDBKeyRange,
|
||||||
JSZip: yomichanTest.JSZip,
|
JSZip: yomichanTest.JSZip,
|
||||||
|
Loading…
Reference in New Issue
Block a user