Replace XMLHttpRequest usage with the Fetch API in inlineImages (in test/driver.js)

This is the final part in a series of patches that try to re-implement PR 14287 in smaller steps.

Besides converting `inlineImages` to use the Fetch API, this patch also combines the `inlineImages` and `resolveImages` functions since they are always used together.
This commit is contained in:
Jonas Jenwald 2022-03-09 10:55:27 +01:00
parent 3e593cfc1d
commit b3f4758183

View File

@ -78,29 +78,52 @@ function writeSVG(svgElement, ctx) {
});
}
function inlineImages(images) {
const imagePromises = [];
for (let i = 0, ii = images.length; i < ii; i++) {
imagePromises.push(
new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.onload = function () {
async function inlineImages(node, silentErrors = false) {
const promises = [];
for (const image of node.getElementsByTagName("img")) {
const url = image.src;
promises.push(
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.blob();
})
.then(blob => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = function () {
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(xhr.response);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
})
.then(dataUrl => {
return new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = evt => {
if (silentErrors) {
resolve();
return;
}
reject(evt);
};
xhr.onerror = function (e) {
reject(new Error("Error fetching inline image " + e));
};
xhr.open("GET", images[i].src);
xhr.send();
image.src = dataUrl;
});
})
.catch(reason => {
throw new Error(`Error inlining image (${url}): ${reason}`);
})
);
}
return Promise.all(imagePromises);
await Promise.all(promises);
}
async function convertCanvasesToImages(annotationCanvasMap, outputScale) {
@ -125,29 +148,6 @@ async function convertCanvasesToImages(annotationCanvasMap, outputScale) {
return results;
}
async function resolveImages(node, silentErrors = false) {
const images = node.getElementsByTagName("img");
const data = await inlineImages(images);
const loadedPromises = [];
for (let i = 0, ii = data.length; i < ii; i++) {
loadedPromises.push(
new Promise(function (resolveImage, rejectImage) {
images[i].onload = resolveImage;
images[i].onerror = function (e) {
if (silentErrors) {
resolveImage();
} else {
rejectImage(new Error("Error loading image " + e));
}
};
images[i].src = data[i];
})
);
}
await Promise.all(loadedPromises);
}
class Rasterize {
/**
* For the reference tests, the full content of the various layers must be
@ -236,7 +236,7 @@ class Rasterize {
AnnotationLayer.render(parameters);
// Inline SVG images from text annotations.
await resolveImages(div);
await inlineImages(div);
foreignObject.appendChild(div);
svg.appendChild(foreignObject);
@ -300,7 +300,7 @@ class Rasterize {
});
// Some unsupported type of images (e.g. tiff) lead to errors.
await resolveImages(div, /* silentErrors = */ true);
await inlineImages(div, /* silentErrors = */ true);
svg.appendChild(foreignObject);
await writeSVG(svg, ctx);