45 个版本 (27 个重大更改)

0.49.0 2020年7月13日
0.48.2 2020年6月26日
0.38.0 2020年3月28日
0.23.0 2019年11月5日

#31 in #loader

Download history 1/week @ 2024-03-11 286/week @ 2024-04-01

每月132 次下载
用于 deno_cli_snapshots

MIT 许可证

48MB
735K SLoC

JavaScript 695K SLoC // 0.1% comments TypeScript 39K SLoC // 0.3% comments Rust 450 SLoC // 0.0% comments

Deno TypeScript 包

crates docs

此包提供在构建过程中编译 TypeScript、打包并创建 V8 快照的实用程序。快照允许可执行文件快速启动。

system_loader.js

这是一个 System 模块加载器的最小化实现。它专门设计用于加载从 TypeScript 发射的模块,模块格式为 "system",并提供了单个 "outfile",通常称为打包。

因为这个加载器将成为在 Deno.bundle()deno bundle 下发射的打包的一部分,它具有最少的注释和非常简短、隐晦的语法,这并不易于自我解释。因此,在这里提供了关于此文件的指南。

System 模块打包期望存在一个 System.register() 函数来注册模块。从 TypeScript 发射到单个输出文件的模块始终传递 3 个参数:模块指定符、该模块依赖的模块指定符字符串数组,以及最后是模块工厂。

模块工厂需要传递两个参数,一个用于导出值的函数和一个上下文对象。我们必须绑定环境中的某些信息来提供这些参数,因此 gC 获取上下文,而 gE 获取要传递给工厂的导出函数。上下文包含诸如模块指定符、动态 import() 的引用以及 import.meta 的等价物等信息。导出函数接受一个命名导出及其值的两个参数,或者一个包含命名导出键及其值的对象记录。

目前,TypeScript 不会重新编写解析为静态字符串的动态导入(请参阅 microsoft/TypeScript#37429),这意味着已包含在包中的动态导入的导入指定符不会自动匹配已注册在包中的模块指定符。《di()》函数提供了尝试识别相对导入指定符并将它们解析为包内指定符的能力。如果它这样做,它将解析模块的导出,否则它将简单地传递模块指定符给 import() 并返回结果承诺。

工厂的运行由 rF() 处理。当工厂运行时,它返回一个包含两个键的对象,分别是 executesetters。其中 execute 是一个函数,用于最终确定模块的实例化,而 setters 是一个函数数组,用于设置依赖模块的导出值。

gExp()gExpA() 是递归函数,用于返回给定模块的导出。它将确定模块是否已完全初始化,如果没有,它将收集依赖项的导出,通过 setters 在模块中设置这些导出,并运行模块的 execute()。然后它总是返回或解析模块的导出。

截至 TypeScript 3.8,当输出 ES 或 System 模块时支持顶层 await。当 Deno 创建模块包时,它创建一个有效的、自包含的 ES 模块,导出创建包时使用的 "main" 模块的导出。如果包中的模块需要顶层 await,那么 execute() 函数被输出为一个异步函数,返回一个承诺。这意味着为了导出主模块的值,实例化需要利用顶层 await。

在撰写本文时,尽管 V8 和其他 JavaScript 引擎已实现了顶层 await,但尚无浏览器实现它,这意味着大多数浏览器无法消费需要顶层 await 的模块。

为了允许更多浏览器消费包,有一个传递给 __instantiate() 函数的参数,以确定代码是否异步启动。当输出包含需要顶层 await 的模块的包时,Deno 将检测这一点并使用 await __instantiate(main, true)

system_loader_es5.js》是《system_loader.js》的编译版本,旨在与 ES5 或更高版本兼容,并且当捆绑目标小于 ES2017 时将使用它。虽然 ES3 仍然是一个潜在的目标,可以通过在《tsconfig.json》中传递给 Deno,但任何生成的捆绑包都不会兼容,因为需要利用诸如《Object.defineProperty()》之类的功能。

依赖项

~52MB
~1M SLoC