JavaScript值上的Web IDL类型转换
这个包在JavaScript中实现了根据给定值转换给定JavaScript值的算法 Web IDL 类型。
目标是您应该能够编写类似的代码
"use strict";
const conversions = require("webidl-conversions");
function doStuff(x, y) {
x = conversions["boolean"](x);
y = conversions["unsigned long"](y);
// actual algorithm code here
}
你的函数 doStuff 将表现为相同的Web IDL操作声明为
undefined doStuff(boolean x, unsigned long y);
API
此包的主模块的默认导出是一个具有各种方法的对象,每个方法对应于不同的Web IDL类型。在JavaScript值上调用每个方法时,将返回通过Web IDL转换规则后产生的新JavaScript值。(详情见下文。)另外,如果指定了Web IDL算法,该方法也可能抛出错误:例如 conversions["float"](NaN) 我会扔一个 TypeError。
每个方法还接受用于其他选项的第二个可选参数。对于抛出错误的转换方法,一个字符串选项 { context } 可以在错误消息中提供更多信息。(例如, conversions["float"](NaN, { context: "Argument 1 of Interface's operation" }) 会抛出带有消息的错误吗 "Argument 1 of Interface's operation is not a finite floating-point value.")
如果我们正在处理多个JavaScript领域(例如使用Node.js创建的领域) 虚拟机 模块或HTML iframe 元素),并且需要抛出来自另一个领域的异常,则可以提供对象选项 globals 包含以下属性:
{
globals: {
Number,
String,
TypeError
}
}
抛出异常时将使用这些特定的函数。
特定的转换也可以接受其他选项,其详细信息可以在下面找到。
转换实现
实现了Web IDL规范中所有基本类型的转换:
anyundefinedboolean- 整数类型,可以另外提供布尔选项
{ clamp, enforceRange }作为第二个参数 float,unrestricted floatdouble,unrestricted doubleDOMString,可以另外提供布尔选项{ treatNullAsEmptyString }作为第二个参数ByteString,USVStringobject- 缓冲源类型,其中一些可以另外提供布尔选项
{ allowShared, allowResizable }作为第二个参数
此外,为了方便起见,实现了以下派生类型定义:
ArrayBufferView,可以另外提供布尔选项{ allowShared, allowResizable }作为第二个参数BufferSourceDOMTimeStamp
派生类型,如可空类型、承诺类型、序列、记录等,不被这个库处理。你不妨调查一下 webidl2js 项目。
关于…的笔记 long long 类型
这个 long long 和 unsigned long long Web IDL类型可以保存不能存储在JavaScript数字中的值。当我们在转换过程中使用BigInt时,转换仍然是准确的,但是在 unsigned long long 我们根本无法在JavaScript中表示一些可能的输出值。例如,转换JavaScript编号 -1 到Web IDL unsigned long long 应该产生Web IDL值吗 18446744073709551615。因为我们用JavaScript表示Web IDL值,所以我们不能表示 18446744073709551615,所以我们所能做的就是 18446744073709551616 作为输出。
为了减轻这种情况,我们可以从转换函数返回原始的BigInt值,但现在还没有实现。如果您的用例需要这样的精度, 提出一个问题。
另一方面, long long 转换总是精确的,因为输入值永远不会比输出值更精确。
关于 BufferSource 类型
所有的 BufferSource 类型将在相关时抛出 ArrayBuffer 已经分离了。严格来说,这并不属于 指定转换算法,而是……的一部分 找参考/找副本 算法。为了方便和易于实现,我们在这里合并了它们,但如果将来需要将它们分开,请打开一个问题,以便我们进行调查。
背景
从概念上讲,这里实际发生的事情是相当奇怪的。让我们试着解释一下。
Web IDL有自己的类型系统。当人们在web平台规范中编写算法时,他们通常对web IDL值进行操作,即web IDL类型的实例。例如,如果他们为我们的 doStuff 手术以上,他们会治疗 x 的Web IDL值 Web IDL类型 boolean。关键是,他们会 不 治疗 x 作为JavaScript变量,其值要么是JavaScript true 或 false。相反,它们在一个完全不同的类型系统中工作,有自己的规则。
与它的类型系统不同,Web IDL定义了 “绑定” 将类型系统转换为JavaScript。这包含如下规则:当您将JavaScript值传递给显示给定Web IDL操作的JavaScript方法时,如何将其转换为Web IDL值?例如,一个JavaScript true 传递到Web IDL的位置 boolean 参数变成了Web IDL true。但是,JavaScript true 在a的位置传递 Web IDL unsigned long 成为Web IDL 1。等等......。
最后,我们有了实际的实现代码。这通常是c++ (或生锈)。当然,实现有自己的类型系统。因此,当他们实现Web IDL算法时,他们实际上并不使用Web IDL值,因为这些值在规范之外并不是“真实的”。相反,实现以这样一种方式应用Web IDL绑定规则,将传入的JavaScript值转换为c++值。例如,if代码在浏览器中调用 doStuff(true, true),那么实现代码最终会收到一个c++ bool 包含 true 和一个c++ uint32_t 包含 1。
这样做的好处是,实现可以抽象出所有的转换逻辑,让Web IDL处理它,并专注于用已经提供的正确类型的值在c++中实现相关的方法。简而言之,这就是Web IDL的回报。
获得回报是我们的目标 这 项目—但是用于JavaScript实现,而不是c++实现。也就是说,这个库旨在使JavaScript开发人员更容易编写行为类似于给定Web IDL操作的函数。所以从概念上讲,转换管道,它的一般形式是JavaScript值乘以Web IDL值乘以实现语言值,在这种情况下变成了JavaScript值乘以Web IDL值乘以JavaScript值。 中间步骤是执行所有逻辑的地方:JavaScript true 成为Web IDL 1 在unsigned long上下文中,然后变成JavaScript 1。
不要用这个
说真的,你为什么要用这个?你真的不应该。Web IDL是……奇怪的,您不应该模仿它的语义。如果您正在寻找一个通用的参数处理库,那么您应该找到一个具有比Web IDL更好规则的库。一般来说,你的JavaScript不应该试图变得更像Web IDL;如果有的话,我们应该修复Web IDL,使其更像JavaScript。
这个 只有 应该使用它的人是那些试图创建web IDL中定义的web平台接口的忠实实现(或填充)的人。它的主要消费者是美国人 jsdom 项目。