For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/proposal-json-modules.md.
  • 简体中文
  • JSON Modules S4

    中文标题:JSON 模块

    提案概览
    提案速览

    该提案通过利用带有 type: "json" 的导入属性,标准化了跨 JavaScript 环境的 JSON 模块导入。它通过在导入位置要求显式属性来解决意外 MIME 类型的安全问题,同时允许宿主定义额外的检查。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    JSON 模块

    提案发起人:Sven Sauleau (@xtuc), Daniel Ehrenberg (@littledan), Myles Borins (@MylesBorins), Dan Clark (@dandclark), 以及 (@nicolo-ribaudo).

    状态:第 4 阶段。

    本提案现已 合并到 ECMA-262 规范中

    概述

    JSON 模块提案基于 导入属性提案 来添加以跨 JavaScript 环境通用的方式导入 JSON 模块的能力。

    开发者将能够如下导入 JSON 模块:

    import json from "./foo.json" with { type: "json" };
    import("foo.json", { with: { type: "json" } });

    注意:本提案最初是 导入属性提案 的一部分,但在 2020 年 7 月的会议上被 决议 拆分为单独的提案。

    动机

    标准轨道的 JSON ES 模块曾被 提议,以允许 JavaScript 模块轻松导入 JSON 数据文件,类似于许多非标准 JavaScript 模块系统中的支持方式。这个想法很快得到了 Web 开发者和浏览器的广泛支持,并已合并到 HTML 中,微软为 V8/Chromium 创建了一个实现。

    然而,在 一个 issue 中,Ryosuke Niwa (Apple) 和 Anne van Kesteren (Mozilla) 提出,在导入 JSON 模块和类似不能执行代码的模块类型时,如果要求一些语法标记,安全性将会提高,以防止响应服务器意外提供不同的 MIME 类型导致代码意外执行的情况。解决方案是在 MIME 类型之外,以某种方式指示模块是 JSON,或者一般地,指示其不应被执行。导入属性 提供了实现这一点的机制,使我们能够重新引入 JSON 模块。

    与其让宿主自由实现 JSON 模块,不如在 TC39 中对其进行规范,以确保它们在所有符合 ECMA262 的宿主中行为一致。

    提议的语义和互操作性

    如果模块导入具有键为 type 且值为 json 的属性,宿主必须要么使导入失败,要么将其视为 JSON 模块。具体而言,这意味着模块的内容被解析为 JSON,并且生成的 JSON 对象是模块的默认导出(该模块没有命名导出)。

    每个 JavaScript 宿主应提供一种次要的方式来检查模块是否为 JSON 模块。例如,在 Web 上,将检查 MIME 类型是否为 JSON MIME 类型。在“本地”桌面/服务器/嵌入环境中,可能会检查文件扩展名(可能在跟随符号链接之后)。在导入位置指示 type: "json",而不是 通过该其他机制,以防止开头部分提到的权限提升问题。

    模块图中所有针对同一 JSON 模块的导入语句将求值为同一个可变对象,如 #54 中讨论的那样。

    尽管如此,对没有属性的模块加载的解释仍然是宿主/实现定义的,因此不 要求 with { type: "json" } 也可以实现 JSON 模块。只是 with { type: "json" } 必须在所有地方都得到支持。例如,由 Node.js 而非 TC39 来决定 JSON 模块的导入属性是必需还是可选。

    json 模块之外,未来的 TC39 提案以及宿主可以添加更多属性和模块类型。HTML 和 CSS 模块也在考虑之中,导入时可能会使用类似的显式 type 语法。

    常见问题

    此提案如何与缓存协同工作?

    type 属性是否属于模块缓存键的一部分,由宿主决定(对于所有导入属性都是如此)。

    为什么 JSON 模块不支持命名导出?

    在早期 HTML 针对 JSON 模块的努力中,曾 考虑 为解析后的 JSON 值的每个顶级属性提供“命名导出”。一方面,某些 JavaScript 工具实现了命名导出,并且一些开发者发现它们对某些形式的 tree shaking 更符合人体工程学/更友好。然而,本提案未选择它们,因为:

    • 它们并非完全通用:并非所有 JSON 文档都是对象。
    • 将 JSON 文档概念上视为 “单个事物” 而不是文件中恰好并排放置的多个事物,是合理的。

    规范