Jsdom: 添加 URL.createObjectURL 和 URL.revokeObjectURL

创建于 2017-01-31  ·  26评论  ·  资料来源: jsdom/jsdom

嗨, jsdom已经支持URL构造函数,但不是这两个静态方法,它们在大多数现代浏览器中都受支持。

创建对象URL
撤销对象URL
我可以用吗

feature

最有用的评论

@fredvollmer如果在 jsdom 中使用 jest 并且你想 noop 这个函数,你可以将此代码添加到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吗?

我因在jsdom使用jspdf被阻止。

不,那里的代码似乎是创建数据 URL,而不是 Blob 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 没有严格遵循规范,如果您两次传递相同的 args 或任何不期望的类型,如数字或数组, 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 ,上面的代码看起来不错,可以添加到那里吗? 你能加吗?

它应该做的不仅仅是制作 Blob URL。 它应该随后允许将如此生成的 URL 提供给XMLHttpRequest

它应该做的不仅仅是制作 Blob URL。 它应该随后允许将如此生成的 URL 提供给 XMLHttpRequest 之类的东西。

它需要那个吗? 用例是什么? XMLHttpRequest的现有逻辑会很好地处理它吗?

我不确定jsdom的目标是否是复制浏览器所做的确切行为。
如果是这种情况,我们正在编写浏览器。

IMO 我们应该推迟到有实际用例。

我们还能做些什么来推动这一进程?

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

serializeURL()比规范中描述的算法做的更多。
我们应该完全按照规范使用它还是实现它?

如果它们实际上不起作用(当被 XHR、img 元素等使用时),绝对没有兴趣将对象 URL 添加到 jsdom。 仅仅创造它们是非常非常无趣的。 你可以用几行代码做到这一点; 你不需要一个完整的 jsdom 实现。

好的,那么需要什么来实现呢?

除了允许在 Node 中使用 DOM API 之外,拥有这样一个浏览器来运行自动化测试是非常有帮助的。

但是 Node 使用的一个特定用例是,如果您在创建 Blob 的地方运行浏览器/Node 代码,则可以在两种环境中使用此方法以允许您内省内容(因为浏览器至少不允许这个)。 (在我的例子中,它允许我避免在 IndexedDB(和postMessage )使用的结构化克隆算法中编写节点特定的代码来克隆 Blob。)

Blob URL 满足在独立于服务器的内存中工作的特殊需求。 我认为 Blob URL 在data: URL 上有三个独特的方面(除了能够更轻松地组合它们而无需转义等)。

一是除了 in-memory content 之外,他们可以引用文件而无需在 URL 中对整个文件的内容进行编码(并且在使用之前不需要取消引用)。

二是它们可能对安全/隐私有用,可以避免数据在浏览器会话之外或用户浏览器之外的持久化。

第三是即使在会话中也可以撤销 Blob URL,从而允许引用过期(例如,如果您创建一个图像,通过 Blob URL 显示它,然后用户删除该图像,您可以撤销该 URL,以便 Blob URL 不能重复使用,不像data URL 的情况)。

如果它们实际上不起作用(当被 XHR、img 元素等使用时),绝对没有兴趣将对象 URL 添加到 jsdom。 仅仅创造它们是非常非常无趣的。

我想在react-snapshot的帮助下react-mapbox-gl ,它反过来使用 mapbox-gl ,它使用webworkify 。 并且过程失败,因为

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

我对在服务器上实际渲染地图不感兴趣,我只想在服务器上渲染占位符而不是地图,但是这个错误阻止了它。

你可以用几行代码做到这一点; 你不需要一个完整的 jsdom 实现。

有没有办法可以修补 jsdom 至少为此添加 noop 功能? 我想它会失败,但这至少是起点。

请参阅自述文件: https :

谢谢。 很遗憾我一直坚持使用旧的 api 例如jsdom.env ,它没有这个

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

(facepalm) 会有点难

UPD

created回调

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

此功能请求的状态如何? 拥有它肯定会很有用。

@fredvollmer如果在 jsdom 中使用 jest 并且你想 noop 这个函数,你可以将此代码添加到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 吗? 基本上,我想消除来自 uncss 正在使用的 jsdom 的关于createObjectURL的 jsdom 错误。

提前致谢!

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

只是为了使它更加清楚,做类似的事情

function noOp () { }

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

当您将其放在 jest 配置的“setupFiles”文件中时才有效。 所以在你的 package.json 或任何你拥有的地方
"jest": { "setupFiles": [ "<rootDir>/internals/testing/setup_file.js" ], }
您将其他人编写的代码放入该文件中。 (如果该文件不存在,您可能需要创建它)

希望这可以帮助任何对解决方案感到困惑的人

img.src = URL.createObjectURL(blob);

不工作,在检查 jest 测试用例文件时收到错误URL.createObjectURL 不是函数
有没有其他方法可以将返回的 blob 分配给图像 src ? 我被屏蔽了

这是 hacky,我不推荐它,但我为 Node.js做了一个实现
在使用它之前,请确保您知道自己在做什么。

此页面是否有帮助?
0 / 5 - 0 等级