Jsdom: Добавьте URL.createObjectURL и URL.revokeObjectURL

Созданный на 31 янв. 2017  ·  26Комментарии  ·  Источник: jsdom/jsdom

Привет, jsdom уже поддерживает конструктор URL , но не эти 2 статических метода, они поддерживаются в большинстве современных браузеров.

createObjectURL
revokeObjectURL
Могу ли я использовать

Самый полезный комментарий

@fredvollmer, если вы используете jest с jsdom и хотите отключить эту функцию, вы можете добавить этот код в setupTest.js (или в эквивалентный сценарий установки)

function noOp () { }

if (typeof window.URL.createObjectURL === 'undefined') {
  Object.defineProperty(window.URL, 'createObjectURL', { value: noOp})
}

Все 26 Комментарий

Можно ли использовать реализацию в 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

[email protected]

@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.
Перед использованием убедитесь, что вы знаете, что делаете.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

cg433n picture cg433n  ·  3Комментарии

jacekpl picture jacekpl  ·  4Комментарии

kilianc picture kilianc  ·  4Комментарии

tolmasky picture tolmasky  ·  4Комментарии

mitar picture mitar  ·  4Комментарии