Skip to content

Commit

Permalink
remove dynamism in imports (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
Schniz committed May 28, 2023
1 parent 004e94d commit 8d4f786
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 8 deletions.
8 changes: 8 additions & 0 deletions .changeset/serious-moons-remain.md
@@ -0,0 +1,8 @@
---
'@edge-runtime/primitives': patch
---

remove dynamism in imports: add a `${primitive}.text.js` file that will be
required, instead of using `fs` to read the file at runtime.

This will help bundlers to statically analyze the code.
29 changes: 29 additions & 0 deletions packages/primitives/scripts/build.ts
Expand Up @@ -142,6 +142,35 @@ async function bundlePackage() {
],
})

if (true) {
const loadSource = fs.promises.readFile(
resolve(__dirname, '../dist/load.js'),
'utf8'
)
const files = new Set<string>()
const loadSourceWithPolyfills = (await loadSource).replace(
/injectSourceCode\("(.+)"\)/g,
(_, filename) => {
files.add(filename)
return `require(${JSON.stringify(`${filename}.text.js`)})`
}
)
await fs.promises.writeFile(
resolve(__dirname, '../dist/load.js'),
loadSourceWithPolyfills
)
for (const file of files) {
const contents = await fs.promises.readFile(
resolve(__dirname, '../dist', file),
'utf8'
)
await fs.promises.writeFile(
resolve(__dirname, '../dist', `${file}.text.js`),
`module.exports = ${JSON.stringify(contents)}`
)
}
}

for (const file of filesExt.map((file) => parse(file).name)) {
if (file !== 'index') {
await fs.promises.mkdir(resolve(__dirname, `../${file}`)).catch(() => {})
Expand Down
6 changes: 6 additions & 0 deletions packages/primitives/src/injectSourceCode.d.ts
@@ -0,0 +1,6 @@
/**
* Injects the source code of a file into a string.
* This relies on the build script to generate a file with the same name as the
* file to be injected, but with a `.text.js` extension.
*/
declare const injectSourceCode: (path: string) => string
29 changes: 21 additions & 8 deletions packages/primitives/src/primitives/load.js
Expand Up @@ -2,7 +2,6 @@

import Module from 'module'
import { dirname, join } from 'path'
import { readFileSync } from 'fs'
import nodeCrypto from 'crypto'

/**
Expand All @@ -12,22 +11,22 @@ import nodeCrypto from 'crypto'
* @param {string} params.path
* @param {Set<string>} [params.references]
* @param {Record<string, any>} params.scopedContext
* @param {string} params.sourceCode
* @returns {any}
*/
function requireWithFakeGlobalScope(params) {
const resolved = params.path
const getModuleCode = `(function(module,exports,require,__dirname,__filename,globalThis,${Object.keys(
params.scopedContext
).join(',')}) {${readFileSync(resolved, 'utf-8')}\n})`
).join(',')}) {${params.sourceCode}\n})`
const module = {
exports: {},
loaded: false,
id: resolved,
id: params.path,
}

// @ts-ignore
const moduleRequire = (Module.createRequire || Module.createRequireFromPath)(
resolved
params.path
)

/** @param {string} pathToRequire */
Expand All @@ -48,8 +47,8 @@ function requireWithFakeGlobalScope(params) {
module,
module.exports,
throwingRequire,
dirname(resolved),
resolved,
dirname(params.path),
params.path,
params.context,
...Object.values(params.scopedContext)
)
Expand All @@ -68,6 +67,7 @@ export function load(scopedContext = {}) {
const encodingImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './encoding.js'),
sourceCode: injectSourceCode('./encoding.js'),
scopedContext: scopedContext,
})
assign(context, {
Expand All @@ -81,6 +81,7 @@ export function load(scopedContext = {}) {
const consoleImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './console.js'),
sourceCode: injectSourceCode('./console.js'),
scopedContext: scopedContext,
})
assign(context, { console: consoleImpl.console })
Expand All @@ -89,6 +90,7 @@ export function load(scopedContext = {}) {
const eventsImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './events.js'),
sourceCode: injectSourceCode('./events.js'),
scopedContext: scopedContext,
})
assign(context, {
Expand All @@ -103,13 +105,15 @@ export function load(scopedContext = {}) {
const streamsImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './streams.js'),
sourceCode: injectSourceCode('./streams.js'),
scopedContext: { ...scopedContext },
})

/** @type {import('../../type-definitions/text-encoding-streams')} */
const textEncodingStreamImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './text-encoding-streams.js'),
sourceCode: injectSourceCode('./text-encoding-streams.js'),
scopedContext: { ...streamsImpl, ...scopedContext },
})

Expand All @@ -128,6 +132,7 @@ export function load(scopedContext = {}) {
const abortControllerImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './abort-controller.js'),
sourceCode: injectSourceCode('./abort-controller.js'),
scopedContext: { ...eventsImpl, ...scopedContext },
})
assign(context, {
Expand All @@ -140,6 +145,7 @@ export function load(scopedContext = {}) {
const urlImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './url.js'),
sourceCode: injectSourceCode('./url.js'),
scopedContext: { ...scopedContext },
})
assign(context, {
Expand All @@ -152,6 +158,7 @@ export function load(scopedContext = {}) {
const blobImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './blob.js'),
sourceCode: injectSourceCode('./blob.js'),
scopedContext: { ...streamsImpl, ...scopedContext },
})
assign(context, {
Expand All @@ -162,6 +169,7 @@ export function load(scopedContext = {}) {
const structuredCloneImpl = requireWithFakeGlobalScope({
path: join(__dirname, './structured-clone.js'),
context,
sourceCode: injectSourceCode('./structured-clone.js'),
scopedContext: { ...streamsImpl, ...scopedContext },
})
assign(context, {
Expand All @@ -172,6 +180,7 @@ export function load(scopedContext = {}) {
const fetchImpl = requireWithFakeGlobalScope({
context,
path: join(__dirname, './fetch.js'),
sourceCode: injectSourceCode('./fetch.js'),
cache: new Map([
['abort-controller', { exports: abortControllerImpl }],
['streams', { exports: streamsImpl }],
Expand Down Expand Up @@ -218,9 +227,12 @@ function getCrypto(context, scopedContext) {
CryptoKey: scopedContext.CryptoKey || globalThis.CryptoKey,
SubtleCrypto: scopedContext.SubtleCrypto || globalThis.SubtleCrypto,
}
} else if (nodeCrypto.webcrypto) {
} else if (
// @ts-ignore
nodeCrypto.webcrypto
) {
/** @type {any} */
// @ts-ignore
const webcrypto = nodeCrypto.webcrypto
return {
crypto: webcrypto,
Expand All @@ -233,6 +245,7 @@ function getCrypto(context, scopedContext) {
return requireWithFakeGlobalScope({
context,
path: join(__dirname, './crypto.js'),
sourceCode: injectSourceCode('./crypto.js'),
scopedContext: {
...scopedContext,
},
Expand Down

1 comment on commit 8d4f786

@vercel
Copy link

@vercel vercel bot commented on 8d4f786 May 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

edge-runtime – ./

edge-runtime-git-main.vercel.sh
edge-runtime.vercel.sh
edge-runtime.vercel.app

Please sign in to comment.