Jsdom: Ajouter URL.createObjectURL et URL.revokeObjectURL

Créé le 31 janv. 2017  ·  26Commentaires  ·  Source: jsdom/jsdom

Bonjour, jsdom supporte déjà le constructeur URL , mais pas ces 2 méthodes statiques, elles sont supportées dans la plupart des navigateurs modernes.

createObjectURL
révoquerObjetURL
Puis-je utiliser

feature

Commentaire le plus utile

@fredvollmer si vous utilisez jest avec jsdom et que vous souhaitez noop cette fonction, vous pouvez ajouter ce code à setupTest.js (ou un script de configuration équivalent)

function noOp () { }

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

Tous les 26 commentaires

L'implémentation dans https://github.com/eligrey/Blob.js peut-elle être utilisée dans jsdom ?

Je suis bloqué par cela pour avoir utilisé jspdf dans jsdom .

Non, le code semble créer des URL de données, pas des URL d'objets blob. Quelqu'un doit implémenter correctement la spécification sur https://w3c.github.io/FileAPI/#dfn -createObjectURL

Je ne suis pas familier avec cela, est-ce que ce sera quelque chose comme ça?

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 peut être uuidV4

Je pense que Chrome ne suit pas strictement les spécifications, URL.revokeObjectURL ne lancera pas NetworkError si vous passez deux fois les mêmes arguments ou tout type non attendu, comme un nombre ou un tableau.

Éditer:
La même chose se produit avec Firefox, pour que l'implémentation reste simple et comme les navigateurs, je pense qu'il n'est pas nécessaire d'avoir un magasin de blob et que URL.revokeObjectURL peut être une fonction noop.

Cela signifie:

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

Je suppose qu'il y a déjà un serializeHost() quelque part dans le code.

Une dernière chose est :

Si sérialisé est "null", définissez-le sur une valeur définie par l'implémentation.

Que signifie « valeur définie par la mise en œuvre » ?

On dirait que j'ai des réponses à toutes les questions.
http://stackoverflow.com/questions/42452543/what-does-implementation-defined-value-in-fileapi-unicodebloburl-mean/42452714#42452714

Je pense qu'il est prêt à être mis en œuvre sur https://github.com/jsdom/whatwg-url

MISE À JOUR : Il s'avère que whatwg-url a la plupart des choses disponibles. Donc je suppose que le code est simplement :

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

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

Cependant, je ne sais pas comment le whatwg-url est organisé. Donc je ne sais pas comment mettre le code.

@domenic , le code ci-dessus a-

Il devrait faire plus que simplement créer les URL Blob. Il devrait par la suite permettre à une URL ainsi générée d'être fournie à des personnes comme XMLHttpRequest .

Il devrait faire plus que simplement créer les URL Blob. Il devrait par la suite permettre à une URL ainsi générée d'être fournie à des personnes comme XMLHttpRequest.

A-t-il besoin de ça ? Quels sont les cas d'utilisation ? La logique existante de XMLHttpRequest gérerait-elle très bien ?

Je ne sais pas si le but de jsdom est de reproduire le comportement exact de ce que fait un navigateur.
Si tel est le cas, nous écrivons un navigateur.

OMI, nous devrions reporter cela jusqu'à ce qu'il y ait un cas d'utilisation réel.

Que pouvons-nous faire d'autre pour faire avancer ce dossier ?

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

Le serializeURL() fait un peu plus que l'algorithme décrit dans la spécification.
Devrions-nous l'utiliser ou l'implémenter exactement comme dans la spécification ?

Il n'y a certainement aucun intérêt à ajouter des URL d'objets à jsdom si elles ne fonctionnent pas réellement (lorsqu'elles sont utilisées par XHR, des éléments img, etc.). Le simple fait de les créer est très, très inintéressant. Vous pouvez le faire avec quelques lignes de code ; vous n'avez pas besoin d'une implémentation complète de jsdom pour cela.

Ok, alors qu'est-ce qu'il faut pour implémenter ça?

En plus de permettre l'utilisation des API DOM dans Node, il est très utile d'avoir un tel navigateur pour exécuter des tests automatisés.

Mais un cas d'utilisation spécifique pour l'utilisation de Node est que si vous exécutez du code de navigateur/Node où un Blob est créé, cette méthode peut être utilisée dans les deux environnements pour vous permettre d'introspecter le contenu (comme le navigateur au moins autrement ne permet pas cette). (Dans mon cas, cela me permettrait d'éviter d'écrire du code spécifique au nœud pour le clonage de Blobs dans l'algorithme de clonage structuré tel qu'utilisé par IndexedDB (et postMessage ).)

Les URL de blob répondent à un besoin particulier de travailler en mémoire indépendamment d'un serveur. Je pense qu'il y a trois aspects uniques des URL Blob sur les URL data: (en plus de pouvoir les composer plus facilement sans échapper et autres).

La première est qu'au-delà du contenu en mémoire , ils peuvent référencer des fichiers sans avoir besoin d'encoder l'intégralité du contenu du fichier dans l'URL (et sans exiger qu'il soit déréférencé jusqu'à ce qu'il soit utilisé).

Deuxièmement, ils pourraient être utiles pour la sécurité/la confidentialité en évitant la persistance des données au-delà d'une session de navigateur ou en dehors du navigateur de l'utilisateur.

Troisièmement, les URL Blob peuvent être révoquées même au cours d'une session, ce qui permet aux références d'expirer (par exemple, si vous créez une image, l'affichez via une URL Blob, puis que l'utilisateur supprime l'image, vous pouvez révoquer l'URL afin que le Blob L'URL ne peut pas être réutilisée, contrairement à ce qui serait le cas avec une URL data ).

Il n'y a certainement aucun intérêt à ajouter des URL d'objets à jsdom si elles ne fonctionnent pas réellement (lorsqu'elles sont utilisées par XHR, des éléments img, etc.). Le simple fait de les créer est très, très inintéressant.

Je souhaite effectuer le rendu côté serveur du projet React (CRA) à l'aide de react-snapshot . Mon projet utilise également react-mapbox-gl , qui à son tour utilise mapbox-gl, qui utilise webworkify . Et le processus échoue à cause de

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

Je ne suis pas intéressé par le rendu de la carte sur le serveur, je veux juste rendre un espace réservé au lieu de la carte sur le serveur, mais cette erreur l'empêche.

Vous pouvez le faire avec quelques lignes de code ; vous n'avez pas besoin d'une implémentation complète de jsdom pour cela.

Existe-t-il un moyen de patcher jsdom pour au moins ajouter la fonction noop pour cela? Je suppose que cela échouera, mais ce sera au moins un point de départ.

Voir le fichier readme : https://github.com/tmpvar/jsdom#intervening -before-parsing

Merci. C'est dommage que je sois coincé avec l'ancienne API, par exemple jsdom.env , qui n'a pas cela

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

(facepalm) ce sera un peu plus dur

UPD

il y a created rappel

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

Quel est le statut de cette demande de fonctionnalité ? Il serait certainement utile d'avoir.

@fredvollmer si vous utilisez jest avec jsdom et que vous souhaitez noop cette fonction, vous pouvez ajouter ce code à setupTest.js (ou un script de configuration équivalent)

function noOp () { }

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

@dylanjha je reçois TypeError: Cannot redefine property: createObjectURL

[email protected]

@franciscolorenco tu as raison ! Désolé pour ça... je viens de mettre à jour le code dans l'exemple ci-dessus pour envelopper ce conditionnel et cela fonctionne pour moi : if (typeof window.URL.createObjectURL === 'undefined') {

Essayez-le !

Merci de m'avoir rappelé de revenir ici et de mettre à jour mon exemple.

@dylanjha createObjectURL est défini mais pas une fonction, donc certaines bibliothèques génèrent des erreurs. Une mission a fonctionné pour moi :

window.URL.createObjectURL = noOp

Est-ce que quelqu'un sait si cela peut aussi être appliqué avec gulp? Fondamentalement, je veux faire taire les erreurs jsdom à propos de createObjectURL qui proviennent de jsdom qu'uncss utilise.

Merci d'avance!

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

Juste pour que ce soit plus clair, faire quelque chose comme

function noOp () { }

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

ne fonctionnera
"jest": { "setupFiles": [ "<rootDir>/internals/testing/setup_file.js" ], }
vous mettez ce code écrit par d'autres dans ce fichier. (si ce fichier n'existe pas, vous devrez peut-être le créer)

J'espère que cela aidera toute personne confuse au sujet de la solution

img.src = URL.createObjectURL(blob);

ne fonctionne pas, obtenir une erreur URL.createObjectURL n'est pas une fonction lors de l'
existe-t-il une alternative pour affecter le blob renvoyé à l'image src ? Je suis bloqué

C'est bidon et je ne le recommanderais pas, mais j'ai fait une implémentation simplifiée
Assurez-vous de savoir ce que vous faites avant de l'utiliser.

Cette page vous a été utile?
0 / 5 - 0 notes