Jsdom: URL.createObjectURL und URL.revokeObjectURL hinzufügen

Erstellt am 31. Jan. 2017  ·  26Kommentare  ·  Quelle: jsdom/jsdom

Hallo, jsdom unterstützt bereits den URL Konstruktor, aber nicht diese 2 statischen Methoden, sie werden in den meisten modernen Browsern unterstützt.

createObjectURL
widerrufenObjectURL
Kann ich benutzen

feature

Hilfreichster Kommentar

@fredvollmer Wenn Sie jest mit jsdom verwenden und diese Funktion verwenden möchten, können Sie diesen Code zu setupTest.js (oder einem äquivalenten Setup-Skript) hinzufügen.

function noOp () { }

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

Alle 26 Kommentare

Kann die Implementierung in https://github.com/eligrey/Blob.js in jsdom ?

Ich bin dadurch blockiert, weil ich jspdf in jsdom .

Nein, der Code dort scheint Daten-URLs zu erstellen, keine Blob-URLs. Jemand muss die Spezifikation unter https://w3c.github.io/FileAPI/#dfn -createObjectURL richtig implementieren

Ich kenne mich damit nicht aus, wird es so ähnlich sein?

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 kann uuidV4 sein

Ich denke, Chrome hält sich nicht strikt an die Spezifikation, URL.revokeObjectURL wirft NetworkError wenn Sie dieselben Argumente zweimal oder einen nicht erwarteten Typ übergeben, wie eine Zahl oder ein Array.

Bearbeiten:
Das gleiche passiert mit Firefox, um die Implementierung einfach zu halten, und wie bei den Browsern ist es meiner Meinung nach nicht erforderlich, einen Blob-Speicher zu haben und URL.revokeObjectURL kann eine Noop-Funktion sein.

Das bedeutet:

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

Ich denke, irgendwo im Code ist bereits ein serializeHost() .

Eine letzte Sache ist:

Wenn serialized "null" ist, legen Sie es auf einen von der Implementierung definierten Wert fest.

Was bedeutet "implementierungsdefinierter Wert"?

Anscheinend bekomme ich alle Fragen beantwortet.
http://stackoverflow.com/questions/42452543/what-does-implementation-defined-value-in-fileapi-unicodebloburl-mean/42452714#42452714

Ich denke, es ist bereit für die Implementierung unter https://github.com/jsdom/whatwg-url

UPDATE: Es stellte sich heraus, dass whatwg-url die meisten Dinge verfügbar hat. Also ich denke, der Code ist einfach:

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

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

Allerdings weiß ich nicht, wie das whatwg-url organisiert ist. Weiß also nicht, wie man den Code einfügt.

@domenic , sieht der obige Code gut aus und kann dort hinzugefügt werden? Kannst du es hinzufügen?

Es sollte mehr tun, als nur die Blob-URLs zu erstellen. Es sollte anschließend ermöglichen, dass eine so generierte URL an XMLHttpRequest .

Es sollte mehr tun, als nur die Blob-URLs zu erstellen. Es sollte anschließend ermöglichen, dass eine so generierte URL beispielsweise XMLHttpRequest zur Verfügung gestellt wird.

Braucht es das? Was sind die Anwendungsfälle? Würde die vorhandene Logik von XMLHttpRequest damit gut umgehen?

Ich bin mir nicht sicher, ob das Ziel von jsdom besteht, das genaue Verhalten eines Browsers zu replizieren.
Wenn das der Fall ist, schreiben wir einen Browser.

IMO sollten wir dies aufschieben, bis es einen tatsächlichen Anwendungsfall gibt.

Was können wir noch tun, um dies voranzubringen?

Var-URL = blob:${serializeURL(location.origin)}/${uuid()} ;

Der serializeURL() macht etwas mehr als der in der Spezifikation beschriebene Algorithmus.
Sollten wir es verwenden oder genau wie in der Spezifikation implementieren?

Es besteht definitiv kein Interesse daran, jsdom Objekt-URLs hinzuzufügen, wenn sie nicht wirklich funktionieren (wenn sie von XHR, img-Elementen usw. verwendet werden). Sie nur zu erstellen ist sehr, sehr uninteressant. Sie können dies mit ein paar Zeilen Code tun; Sie brauchen dafür keine ganze jsdom-Implementierung.

Ok, was ist also nötig, um das zu implementieren?

Abgesehen davon, dass DOM-APIs in Node verwendet werden können, ist es sehr hilfreich, einen solchen Browser zum Ausführen automatisierter Tests zu haben.

Ein spezifischer Anwendungsfall für die Node-Nutzung besteht jedoch darin, dass, wenn Sie Browser-/Node-Code ausführen, in dem ein Blob erstellt wird, diese Methode in beiden Umgebungen verwendet werden kann, um Ihnen eine Introspektion der Inhalte zu ermöglichen (da der Browser dies zumindest sonst nicht zulässt). Dies). (In meinem Fall würde ich es vermeiden, knotenspezifischen Code zum Klonen von Blobs im strukturierten Klonalgorithmus zu schreiben, wie er von IndexedDB (und postMessage ) verwendet wird.)

Blob-URLs erfüllen einen besonderen Bedarf, unabhängig von einem Server im Arbeitsspeicher zu arbeiten. Ich denke, es gibt drei einzigartige Aspekte von Blob-URLs über data: URLs (außer der Möglichkeit, sie einfacher zu verfassen, ohne zu entkommen und dergleichen).

Einer ist, dass sie über In-Memory-Inhalte hinaus auf Dateien verweisen können, ohne den gesamten Inhalt der Datei in der URL kodieren zu müssen (und nicht zu erfordern, dass er bis zur Verwendung dereferenziert wird).

Zweitens können sie für die Sicherheit/den Datenschutz nützlich sein, um die Persistenz der Daten über eine Browsersitzung hinaus oder außerhalb des Browsers des Benutzers zu vermeiden.

Drittens können Blob-URLs sogar innerhalb einer Sitzung widerrufen werden, sodass Verweise ablaufen können (z. B. wenn Sie ein Bild erstellen, es über eine Blob-URL anzeigen und der Benutzer das Bild dann löscht, können Sie die URL widerrufen, damit URL kann nicht wiederverwendet werden, anders als es beispielsweise bei einer data URL der Fall wäre).

Es besteht definitiv kein Interesse daran, jsdom Objekt-URLs hinzuzufügen, wenn sie nicht wirklich funktionieren (wenn sie von XHR, img-Elementen usw. verwendet werden). Sie nur zu erstellen ist sehr, sehr uninteressant.

Ich möchte serverseitiges Rendering von React (CRA)-Projekten mit Hilfe von React -Snapshot durchführen . Mein Projekt auch Anwendungen reagieren-MapBox-gl , die wiederum Anwendungen MapBox-gl, die Anwendungen webworkify . Und der Prozess schlägt fehl wegen

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

Ich bin nicht daran interessiert, die Karte tatsächlich auf dem Server zu rendern, ich möchte nur Platzhalter anstelle der Karte auf dem Server rendern, aber dieser Fehler verhindert dies.

Sie können dies mit ein paar Zeilen Code tun; Sie brauchen dafür keine ganze jsdom-Implementierung.

Gibt es eine Möglichkeit, jsdom zumindest zu patchen, um die Noop-Funktion dafür hinzuzufügen? Ich nehme an, es wird scheitern, aber das wird zumindest der Ausgangspunkt sein.

Siehe Readme: https://github.com/tmpvar/jsdom#intervening -before-parsing

Vielen Dank. Es ist schade, dass ich bei der alten API stecke, z. B. jsdom.env , die das nicht hat

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

(facepalm) es wird etwas schwieriger

UPD

es gibt created Rückruf

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

Wie ist der Status dieser Funktionsanfrage? Es wäre sicherlich nützlich zu haben.

@fredvollmer Wenn Sie jest mit jsdom verwenden und diese Funktion verwenden möchten, können Sie diesen Code zu setupTest.js (oder einem äquivalenten Setup-Skript) hinzufügen.

function noOp () { }

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

@dylanjha Ich bekomme TypeError: Cannot redefine property: createObjectURL

[email protected]

@franciscolourenco du hast recht! Tut mir leid... habe gerade den Code im obigen Beispiel aktualisiert, um diese Bedingung einzuschließen, und das funktioniert bei mir: if (typeof window.URL.createObjectURL === 'undefined') {

Probieren Sie das aus!

Danke, dass Sie mich daran erinnert haben, hierher zurückzukehren und mein Beispiel zu aktualisieren.

@dylanjha createObjectURL ist definiert, aber keine Funktion, daher geben einige Bibliotheken Fehler aus. Eine Aufgabe hat bei mir funktioniert:

window.URL.createObjectURL = noOp

Weiß jemand, ob man das auch mit Schluck anwenden kann? Grundsätzlich möchte ich die jsdom-Fehler über createObjectURL , die von jsdom stammen, das uncss verwendet, zum Schweigen bringen.

Danke im Voraus!

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

Nur um es noch deutlicher zu machen, etwas zu tun wie

function noOp () { }

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

funktioniert nur , wenn Sie es in die Datei "setupFiles" Ihrer jest-Konfiguration einfügen. Also in Ihrem package.json oder wo immer Sie es haben
"jest": { "setupFiles": [ "<rootDir>/internals/testing/setup_file.js" ], }
Sie legen den von anderen geschriebenen Code in diese Datei. (Wenn diese Datei nicht existiert, müssen Sie sie möglicherweise erstellen)

Hoffe, das hilft jedem, der über die Lösung verwirrt ist

img.src = URL.createObjectURL(blob);

funktioniert nicht, Fehler URL.createObjectURL ist keine Funktion beim Einchecken der Testfalldatei.
Gibt es eine Alternative, um das zurückgegebene Blob dem Image src zuzuweisen? Ich bin blockiert

Das ist hackig und ich würde es nicht empfehlen, aber ich habe eine vereinfachte Implementierung von createObjectURL und revokeObjectURL für Node.js vorgenommen .
Bitte stellen Sie sicher, dass Sie wissen, was Sie tun, bevor Sie es verwenden.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen