Jsdom: Adicionar URL.createObjectURL e URL.revokeObjectURL

Criado em 31 jan. 2017  ·  26Comentários  ·  Fonte: jsdom/jsdom

Olá, jsdom já suporta o construtor URL , mas não esses 2 métodos estáticos, eles são suportados na maioria dos navegadores modernos.

createObjectURL
revokeObjectURL
Eu posso usar

feature

Comentários muito úteis

@fredvollmer se estiver usando jest com jsdom e quiser adicionar esta função, você pode adicionar este código a setupTest.js (ou um script de configuração equivalente)

function noOp () { }

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

Todos 26 comentários

A implementação em https://github.com/eligrey/Blob.js pode ser usada em jsdom ?

Estou bloqueado por isso por usar jspdf dentro de jsdom .

Não, o código lá parece criar URLs de dados, não URLs de blob. Alguém precisa implementar adequadamente a especificação em https://w3c.github.io/FileAPI/#dfn -createObjectURL

Não estou familiarizado com isso, será algo assim?

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

Acho que o Chrome não está seguindo as especificações estritamente, URL.revokeObjectURL não lançará NetworkError se você passar os mesmos argumentos duas vezes ou qualquer tipo não esperado, como um número ou array.

Editar:
O mesmo acontece com o Firefox, para manter a implementação simples e assim como os navegadores, acho que não é necessário ter um blob store e URL.revokeObjectURL pode ser uma função noop.

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

Eu acho que já existe um serializeHost() em algum lugar do código.

Uma última coisa é:

Se serializado for "nulo", configure-o para um valor definido pela implementação.

O que significa "valor definido pela implementação"?

Parece que todas as perguntas foram respondidas.
http://stackoverflow.com/questions/42452543/what-does-implementation-defined-value-in-fileapi-unicodebloburl-mean/42452714#42452714

Acho que está pronto para ser implementado em https://github.com/jsdom/whatwg-url

ATUALIZAÇÃO: Acontece que whatwg-url tem quase tudo disponível. Então, acho que o código é simplesmente:

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

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

No entanto, não sei como o whatwg-url está organizado. Portanto, não sei como inserir o código.

@domenic , o código acima parece bom e pode ser adicionado lá? Você pode adicionar?

Deve fazer mais do que apenas criar URLs de Blob. Subseqüentemente, ele deve permitir que um URL assim gerado seja fornecido a XMLHttpRequest .

Deve fazer mais do que apenas criar URLs de Blob. Subseqüentemente, ele deve permitir que uma URL assim gerada seja fornecida para nomes como XMLHttpRequest.

Ele precisa disso? Quais são os casos de uso? A lógica existente de XMLHttpRequest lidaria bem com isso?

Não tenho certeza se o objetivo de jsdom é replicar o comportamento exato do que um navegador faz.
Se for esse o caso, estamos escrevendo um navegador.

IMO, devemos adiar isso até que haja um caso de uso real.

O que mais podemos fazer para avançar?

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

O serializeURL() faz um pouco mais do que o algoritmo descrito nas especificações.
Devemos usá-lo ou implementar exatamente como nas especificações?

Definitivamente, não há interesse em adicionar URLs de objeto ao jsdom se eles realmente não funcionarem (quando usados ​​por XHR, elementos img, etc.). Apenas criá-los é muito, muito desinteressante. Você pode fazer isso com algumas linhas de código; você não precisa de uma implementação jsdom inteira para isso.

Ok, então o que é necessário para implementar isso?

Além de permitir que as APIs DOM sejam usadas no Node, é muito útil ter um navegador desse tipo para executar testes automatizados.

Mas um caso de uso específico para o uso do Node é que se você estiver executando o código do navegador / Node onde um Blob é criado, este método pode ser usado em ambos os ambientes para permitir que você faça uma introspecção no conteúdo (como o navegador pelo menos não permite isto). (No meu caso, isso me permitiria evitar a gravação de código específico do Node para clonar Blobs no algoritmo de clonagem estruturado usado por IndexedDB (e postMessage ).)

Os URLs de blob atendem a uma necessidade especial de trabalhar na memória independente de um servidor. Eu acho que há três aspectos exclusivos de URLs de Blob em relação a data: URLs (além de ser capaz de compô-los mais facilmente sem escape e tal).

Uma é que, além do conteúdo na memória, eles podem fazer referência a arquivos sem a necessidade de codificar todo o conteúdo do arquivo dentro da URL (e sem exigir que seja desreferenciado até que seja usado).

A segunda é que eles podem ser úteis para segurança / privacidade, evitando a persistência dos dados além de uma sessão do navegador ou fora do navegador do usuário.

Em terceiro lugar, os URLs do Blob podem ser revogados mesmo dentro de uma sessão, permitindo que as referências expirem (por exemplo, se você criar uma imagem, exibi-la por meio de um URL do Blob e, em seguida, o usuário excluir a imagem, você pode revogar o URL para que o Blob O URL não pode ser reutilizado, ao contrário do que aconteceria com, digamos, um data URL).

Definitivamente, não há interesse em adicionar URLs de objeto ao jsdom se eles realmente não funcionarem (quando usados ​​por XHR, elementos img, etc.). Apenas criá-los é muito, muito desinteressante.

Eu quero fazer a renderização do lado do servidor do projeto React (CRA) com a ajuda do react-snapshot . Meu projeto também usa react-mapbox-gl , que por sua vez usa mapbox-gl, que usa webworkify . E o processo falha por causa de

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

Não estou interessado em realmente renderizar o mapa no servidor, só quero renderizar o espaço reservado em vez do mapa no servidor, mas esse erro evita isso.

Você pode fazer isso com algumas linhas de código; você não precisa de uma implementação jsdom inteira para isso.

Existe uma maneira de corrigir o jsdom para, pelo menos, adicionar a função noop para isso? Suponho que falhará, mas pelo menos esse será o ponto de partida.

Veja o leia-me: https://github.com/tmpvar/jsdom#intervening -before-parsing

Obrigado. É uma pena que eu esteja preso a uma API antiga, por exemplo, jsdom.env , que não tem isso

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

(facepalm) vai ser um pouco mais difícil

UPD

created callback

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

Qual é o status desta solicitação de recurso? Certamente seria útil ter.

@fredvollmer se estiver usando jest com jsdom e quiser adicionar esta função, você pode adicionar este código a setupTest.js (ou um script de configuração equivalente)

function noOp () { }

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

@dylanjha recebo TypeError: Cannot redefine property: createObjectURL

[email protected]

@franciscolourenco você está certo! Desculpe por isso ... acabei de atualizar o código no exemplo acima para envolver nesta condicional e isso está funcionando para mim: if (typeof window.URL.createObjectURL === 'undefined') {

Experimente!

Obrigado por me lembrar de voltar aqui e atualizar meu exemplo.

@dylanjha createObjectURL é definido, mas não é uma função, então algumas bibliotecas geram erros. Uma tarefa funcionou para mim:

window.URL.createObjectURL = noOp

Alguém sabe se isso também pode ser aplicado com gole? Basicamente, eu quero silenciar os erros do jsdom sobre createObjectURL que vêm do jsdom que o uncss está usando.

Desde já, obrigado!

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

Só para deixar mais claro, fazer algo como

function noOp () { }

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

funcionará se você colocá-lo no arquivo "setupFiles" de sua configuração de jest. Então, em seu package.json ou onde quer que você tenha
"jest": { "setupFiles": [ "<rootDir>/internals/testing/setup_file.js" ], }
você coloca aquele código escrito por outros dentro desse arquivo. (se esse arquivo não existir, pode ser necessário criá-lo)

Espero que isso ajude alguém confuso sobre a solução

img.src = URL.createObjectURL (blob);

não está funcionando, obtendo um erro URL.createObjectURL não é uma função durante a verificação no arquivo de caso de teste jest.
existe alguma alternativa para atribuir o blob retornado ao src de imagem? eu estou bloqueado

Isso é hacky e eu não recomendaria, mas fiz uma implementação simplificada
Certifique-se de saber o que está fazendo antes de usá-lo.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

lehni picture lehni  ·  4Comentários

khalyomede picture khalyomede  ·  3Comentários

camelaissani picture camelaissani  ·  4Comentários

jacekpl picture jacekpl  ·  4Comentários

philipwalton picture philipwalton  ·  4Comentários