Привет, jsdom
уже поддерживает конструктор URL
, но не эти 2 статических метода, они поддерживаются в большинстве современных браузеров.
Можно ли использовать реализацию в https://github.com/eligrey/Blob.js в jsdom
?
Я заблокирован этим за использование jspdf
внутри jsdom
.
Нет, там код создается для создания URL-адресов данных, а не URL-адресов больших двоичных объектов. Кому-то необходимо правильно реализовать спецификацию на https://w3c.github.io/FileAPI/#dfn -createObjectURL
Я с этим не знаком, будет ли что-то подобное?
createObjectURL(blob) {
var implementationDefinedValue = ???
var url = `blob:${asciiSerialize(location.origin) || implementationDefinedValue}/${createUUID()}`;
saveToBlobStore(url, blob);
return url;
}
revokeObjectURL(blobUrl) {
// assume `getFromBlobStore()` will not throw
var blob = getFromBlobStore(blobUrl);
if (!blob) {
throw new NetworkError(...);
}
removeFromBlobStore(blobUrl);
}
@unional createUUID
может быть uuidV4
Я думаю, что Chrome не строго следует спецификации, URL.revokeObjectURL
не выдаст NetworkError
если вы передадите одни и те же аргументы дважды или любой тип, который не ожидается, например число или массив.
Редактировать:
То же самое происходит с Firefox, чтобы реализация была простой, и, как и в случае с браузерами, я думаю, что не нужно иметь хранилище BLOB-объектов, и URL.revokeObjectURL
может быть функцией noop.
Это означает:
const uuid = require('uuid/v4');
createObjectURL(blob) {
var implementationDefinedValue = ???
var url = `blob:${asciiSerialize(location.origin) || implementationDefinedValue}/${uuid()}`;
return url;
}
revokeObjectURL(blobUrl) {
return;
}
asciiSerialize(origin) {
if (origin.scheme) {
return `${origin.scheme}://${serializeHost(origin.host)}${origin.port? ':' + +origin.port : ''}`;
}
else {
return 'null';
}
}
serializeHost(host) {
...
}
Я предполагаю, что где-то в коде уже есть serializeHost()
.
И последнее:
Если сериализовано значение «null», установите для него значение, определяемое реализацией.
Что означает «значение, определяемое реализацией»?
Кажется, я получил ответы на все вопросы.
http://stackoverflow.com/questions/42452543/what-does-implementation-defined-value-in-fileapi-unicodebloburl-mean/42452714#42452714
Думаю, он готов к реализации на https://github.com/jsdom/whatwg-url
ОБНОВЛЕНИЕ: оказывается, в whatwg-url
есть большинство доступных вещей. Итак, я предполагаю, что код прост:
const uuid = require('uuid/v4');
createObjectURL(_blob) {
var url = `blob:${serializeURL(location.origin)}/${uuid()}`;
return url;
}
revokeObjectURL(_blobUrl) {
return;
}
Однако я не знаю, как устроен whatwg-url
. Так что не знаю, как вставить код.
@domenic , код выше выглядит хорошо и можно ли туда добавить? Вы можете это добавить?
Он должен делать больше, чем просто создавать URL-адреса Blob. Впоследствии он должен разрешить предоставление созданного таким образом URL-адресам вроде XMLHttpRequest
.
Он должен делать больше, чем просто создавать URL-адреса Blob. Впоследствии он должен разрешить предоставление сгенерированного таким образом URL-адреса подобным XMLHttpRequest.
Это нужно? Какие варианты использования? Будет ли хорошо с этим справляться существующая логика XMLHttpRequest
?
Я не уверен, что цель jsdom
- воспроизвести точное поведение того, что делает браузер.
Если это так, мы пишем браузер.
ИМО, мы должны отложить это до тех пор, пока не появится реальный вариант использования.
Что еще мы можем сделать, чтобы продвинуться вперед?
var url =
blob:${serializeURL(location.origin)}/${uuid()}
;
serializeURL()
делает немного больше, чем алгоритм, описанный в спецификации.
Следует использовать его или реализовать точно так, как указано в спецификации?
Определенно нет никакого интереса в добавлении URL-адресов объектов в jsdom, если они на самом деле не работают (при использовании XHR, элементами img и т. Д.). Просто создавать их очень и очень неинтересно. Вы можете сделать это с помощью нескольких строк кода; для этого вам не нужна полная реализация jsdom.
Итак, что нужно для этого?
Помимо возможности использования DOM API в Node, очень полезно иметь такой браузер для запуска автоматических тестов.
Но конкретный вариант использования Node заключается в том, что если вы используете код браузера / узла, в котором создается Blob, этот метод можно использовать в обеих средах, чтобы вы могли анализировать содержимое (поскольку браузер, по крайней мере, в противном случае не позволяет это). (В моем случае это позволило бы мне избежать написания кода для конкретного узла для клонирования BLOB-объектов в алгоритме структурированного клонирования, который используется IndexedDB (и postMessage
).)
URL-адреса BLOB-объектов удовлетворяют особую потребность в работе с памятью независимо от сервера. Я думаю, что есть три уникальных аспекта URL-адресов Blob по сравнению с URL-адресами data:
(помимо возможности их более легко составлять без экранирования и т. Д.).
Один из них заключается в том, что помимо содержимого в памяти они могут ссылаться на файлы без необходимости кодирования всего содержимого файла в URL-адресе (и не требуя разыменования его до использования).
Во-вторых, они могут быть полезны для безопасности / конфиденциальности, чтобы избежать сохранения данных за пределами сеанса браузера или за пределами браузера пользователя.
В-третьих, URL-адреса BLOB-объектов могут быть отозваны даже в рамках сеанса, что позволяет ссылкам истекать (например, если вы создаете изображение, отображаете его через URL-адрес BLOB-объекта, а затем пользователь удаляет изображение, вы можете отозвать URL-адрес, чтобы Blob URL не может быть использован повторно, в отличие от, скажем, data
URL).
Определенно нет никакого интереса в добавлении URL-адресов объектов в jsdom, если они на самом деле не работают (при использовании XHR, элементами img и т. Д.). Просто создавать их очень и очень неинтересно.
Я хочу сделать рендеринг проекта React (CRA) на стороне сервера с помощью response-snapshot . В моем проекте также используется react-mapbox-gl , который, в свою очередь, использует mapbox-gl, который использует webworkify . И процесс не удается из-за
Error: Uncaught [TypeError: o.URL.createObjectURL is not a function]
Меня не интересует фактическая визуализация карты на сервере, я просто хочу визуализировать заполнитель вместо карты на сервере, но эта ошибка предотвращает это.
Вы можете сделать это с помощью нескольких строк кода; для этого вам не нужна полная реализация jsdom.
Есть ли способ исправить jsdom, чтобы хотя бы добавить для этого функцию noop? Я предполагаю, что это не удастся, но это, по крайней мере, будет отправной точкой.
См. Readme: https://github.com/tmpvar/jsdom#intervening -before-parsing
Спасибо. Жаль, что я застрял со старым API, например jsdom.env
, у которого этого нет
options.beforeParse(this[window]._globalProxy);
(фейспалм) будет немного сложнее
UPD
есть обратный вызов created
created: (err, window) => {
window.URL = { createObjectURL: () => {} }
}
Каков статус этого запроса функции? Было бы, конечно, полезно иметь.
@fredvollmer, если вы используете jest с jsdom и хотите отключить эту функцию, вы можете добавить этот код в setupTest.js
(или в эквивалентный сценарий установки)
function noOp () { }
if (typeof window.URL.createObjectURL === 'undefined') {
Object.defineProperty(window.URL, 'createObjectURL', { value: noOp})
}
@dylanjha Я получаю TypeError: Cannot redefine property: createObjectURL
@franciscolourenco , ты прав! Извините за это ... только что обновил код в приведенном выше примере, чтобы обернуть его в это условие, и это работает для меня: if (typeof window.URL.createObjectURL === 'undefined') {
Попробуйте!
Спасибо, что напомнили мне вернуться сюда и обновить мой пример.
@dylanjha createObjectURL
определяется, но не является функцией, поэтому некоторые библиотеки выдают ошибки. У меня сработало задание:
window.URL.createObjectURL = noOp
Кто-нибудь знает, можно ли это применить и с gulp? В основном я хочу заглушить ошибки jsdom о createObjectURL
которые исходят от jsdom, который использует uncss.
Заранее спасибо!
if (typeof URL !== 'undefined') {
delete URL;
}
Просто, чтобы было максимально понятно, сделайте что-нибудь вроде
function noOp () { }
if (typeof window.URL.createObjectURL === 'undefined') {
Object.defineProperty(window.URL, 'createObjectURL', { value: noOp})
}
будет работать, только если вы поместите его в файл «setupFiles» вашей конфигурации jest. Итак, в вашем package.json или там, где у вас есть
"jest": {
"setupFiles": [
"<rootDir>/internals/testing/setup_file.js"
],
}
вы помещаете этот код, написанный другими, в этот файл. (если этот файл не существует, вам может потребоваться его создать)
Надеюсь, это поможет кому-нибудь запутаться в решении
img.src = URL.createObjectURL (blob);
не работает, появляется URL- адрес ошибки.
есть ли альтернатива назначению возвращенного большого двоичного объекта для изображения src? меня заблокировали
Это хакерство, и я бы не рекомендовал его, но я сделал упрощенную реализацию createObjectURL
и revokeObjectURL
для Node.js.
Перед использованием убедитесь, что вы знаете, что делаете.
Самый полезный комментарий
@fredvollmer, если вы используете jest с jsdom и хотите отключить эту функцию, вы можете добавить этот код в
setupTest.js
(или в эквивалентный сценарий установки)