Jsdom: Agregue URL.createObjectURL y URL.revokeObjectURL

Creado en 31 ene. 2017  ·  26Comentarios  ·  Fuente: jsdom/jsdom

Hola, jsdom ya es compatible con el constructor URL , pero no estos 2 métodos estáticos, son compatibles con la mayoría de los navegadores modernos.

createObjectURL
revokeObjectURL
Puedo usar

feature

Comentario más útil

@fredvollmer si usa jest con jsdom y desea noop esta función, puede agregar este código a setupTest.js (o un script de configuración equivalente)

function noOp () { }

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

Todos 26 comentarios

¿Se puede usar la implementación en https://github.com/eligrey/Blob.js en jsdom ?

Esto me bloquea por usar jspdf dentro de jsdom .

No, el código allí parece crear URL de datos, no URL de blobs. Alguien debe implementar correctamente la especificación en https://w3c.github.io/FileAPI/#dfn -createObjectURL

No estoy familiarizado con esto, ¿será algo como esto?

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 puede ser uuidV4

Creo que Chrome no sigue la especificación estrictamente, URL.revokeObjectURL no arrojará NetworkError si pasa los mismos argumentos dos veces o cualquier tipo no esperado, como un número o una matriz.

Editar:
Lo mismo sucede con Firefox, para mantener la implementación simple y, al igual que los navegadores, creo que no es necesario tener una tienda de blobs y URL.revokeObjectURL puede ser una función noop.

Eso significa:

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) {
  ...
}

Supongo que ya hay un serializeHost() en algún lugar del código.

Una ultima cosa es:

Si serializado es "nulo", establézcalo en un valor definido por la implementación.

¿Qué significa "valor definido por la implementación"?

Parece que me responden todas las preguntas.
http://stackoverflow.com/questions/42452543/what-does-implementation-defined-value-in-fileapi-unicodebloburl-mean/42452714#42452714

Creo que está listo para implementarse en https://github.com/jsdom/whatwg-url

ACTUALIZACIÓN: Resulta que whatwg-url tiene la mayoría de las cosas disponibles. Entonces supongo que el código es simplemente:

const uuid = require('uuid/v4');

createObjectURL(_blob) {
  var url = `blob:${serializeURL(location.origin)}/${uuid()}`;
  return url;
}
revokeObjectURL(_blobUrl) {
  return;
}

Sin embargo, no sé cómo está organizado whatwg-url . Así que no sé cómo introducir el código.

@domenic , ¿el código anterior se ve bien y se puede agregar allí? ¿Puedes agregarlo?

Debería hacer algo más que crear las URL de Blob. Posteriormente, debería permitir que una URL así generada se proporcione a usuarios como XMLHttpRequest .

Debería hacer algo más que crear las URL de Blob. Posteriormente, debería permitir que una URL así generada se proporcione a usuarios como XMLHttpRequest.

¿Necesita eso? ¿Cuáles son los casos de uso? ¿Lo manejaría bien la lógica existente de XMLHttpRequest ?

No estoy seguro de si el objetivo de jsdom es replicar el comportamiento exacto de lo que hace un navegador.
Si ese es el caso, estamos escribiendo un navegador.

En mi opinión, deberíamos aplazar esto hasta que haya un caso de uso real.

¿Qué más podemos hacer para que esto avance?

var url = blob:${serializeURL(location.origin)}/${uuid()} ;

El serializeURL() hace un poco más que el algoritmo descrito en la especificación.
¿Debemos usarlo o implementarlo exactamente como en la especificación?

Definitivamente no hay interés en agregar URL de objetos a jsdom si en realidad no funcionan (cuando las usan XHR, elementos img, etc.). Crearlos es muy, muy poco interesante. Puede hacerlo con unas pocas líneas de código; no necesita una implementación completa de jsdom para eso.

Ok, entonces, ¿qué se necesita para implementar eso?

Además de permitir que las API DOM se utilicen en Node, es muy útil tener un navegador de este tipo para ejecutar pruebas automatizadas.

Pero un caso de uso específico para el uso de Node es que si está ejecutando un navegador / código de Nodo donde se crea un Blob, este método se puede usar en ambos entornos para permitirle introspectar el contenido (ya que el navegador, al menos de lo contrario, no permite esta). (En mi caso, me permitiría evitar escribir código específico de Nodo para clonar Blobs en el algoritmo de clonación estructurado utilizado por IndexedDB (y postMessage )).

Las URL de blobs satisfacen una necesidad especial de trabajar en la memoria independientemente de un servidor. Creo que hay tres aspectos únicos de las URL de Blob sobre las URL de data: (además de poder componerlas más fácilmente sin escapar y demás).

Una es que más allá del contenido en memoria, pueden hacer referencia a archivos sin necesidad de codificar todo el contenido del archivo dentro de la URL (y sin requerir que se elimine la referencia hasta que se use).

El segundo es que pueden ser útiles para la seguridad / privacidad al evitar la persistencia de los datos más allá de una sesión del navegador o fuera del navegador del usuario.

En tercer lugar, las URL de Blob se pueden revocar incluso dentro de una sesión, lo que permite que las referencias caduquen (por ejemplo, si crea una imagen, la muestra a través de una URL de Blob y luego el usuario elimina la imagen, puede revocar la URL para que el Blob La URL no se puede reutilizar, a diferencia de lo que sería el caso con, por ejemplo, una URL de data ).

Definitivamente no hay interés en agregar URL de objetos a jsdom si en realidad no funcionan (cuando las usan XHR, elementos img, etc.). Crearlos es muy, muy poco interesante.

Quiero hacer una representación del lado del servidor del proyecto React (CRA) con la ayuda de react-snapshot . Mi proyecto también usa react-mapbox-gl , que a su vez usa mapbox-gl, que usa webworkify . Y el proceso falla debido a

Error: Uncaught [TypeError: o.URL.createObjectURL is not a function]

No estoy interesado en representar el mapa en el servidor, solo quiero representar el marcador de posición en lugar del mapa en el servidor, pero este error lo impide.

Puede hacerlo con unas pocas líneas de código; no necesita una implementación completa de jsdom para eso.

¿Hay alguna manera de que pueda parchear jsdom al menos para agregar la función noop para esto? Supongo que fallará, pero este al menos será el punto de partida.

Vea el archivo Léame: https://github.com/tmpvar/jsdom#intervening -before-parsing

Gracias. Es una lástima que esté atrapado con una api antigua, por ejemplo, jsdom.env , que no tiene esto

options.beforeParse(this[window]._globalProxy);

(facepalm) será un poco más difícil

UPD

hay created devolución

created: (err, window) => {
  window.URL = { createObjectURL: () => {} }
}

¿Cuál es el estado de esta solicitud de función? Sin duda sería útil tenerlo.

@fredvollmer si usa jest con jsdom y desea noop esta función, puede agregar este código a setupTest.js (o un script de configuración equivalente)

function noOp () { }

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

@dylanjha obtengo TypeError: Cannot redefine property: createObjectURL

[email protected]

@franciscolourenco ¡tienes razón! Lo siento ... acabo de actualizar el código en el ejemplo anterior para ajustar este condicional y eso me funciona: if (typeof window.URL.createObjectURL === 'undefined') {

¡Pruébalo!

Gracias por recordarme que vuelva aquí y actualice mi ejemplo.

@dylanjha createObjectURL está definido pero no es una función, por lo que algunas bibliotecas arrojan errores. Una tarea funcionó para mí:

window.URL.createObjectURL = noOp

¿Alguien sabe si esto también se puede aplicar con gulp? Básicamente, quiero silenciar los errores de jsdom sobre createObjectURL que provienen de jsdom que está usando uncss.

¡Gracias por adelantado!

if (typeof URL !== 'undefined') {
  delete URL;
}

Solo para que quede más claro, haciendo algo como

function noOp () { }

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

sólo funcionará si lo pones dentro del archivo "setupFiles" de tu configuración de broma. Entonces en su package.json o donde tenga
"jest": { "setupFiles": [ "<rootDir>/internals/testing/setup_file.js" ], }
pones ese código escrito por otros dentro de ese archivo. (si ese archivo no existe, es posible que deba crearlo)

Espero que esto ayude a cualquiera que esté confundido acerca de la solución.

img.src = URL.createObjectURL (blob);

no funciona, obteniendo un error URL.createObjectURL no es una función al verificar el archivo de caso de prueba de broma.
¿Hay alguna alternativa para asignar blob devuelto a image src? Estoy bloqueado

Esto es hacky y no lo recomendaría, pero hice una implementación simplificada
Asegúrese de saber lo que está haciendo antes de usarlo.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

khalyomede picture khalyomede  ·  3Comentarios

Progyan1997 picture Progyan1997  ·  3Comentarios

tolmasky picture tolmasky  ·  4Comentarios

cg433n picture cg433n  ·  3Comentarios

kilianc picture kilianc  ·  4Comentarios