edge-runtime © Vercel, released under the MPLv2 License.
Authored and maintained by Vercel with help from contributors.
vercel.com · GitHub Vercel · Twitter @vercel
Developing, testing, and defining the runtime Web APIs for Edge infrastructure.
Home Page: https://edge-runtime.vercel.app
License: Mozilla Public License 2.0
edge-runtime © Vercel, released under the MPLv2 License.
Authored and maintained by Vercel with help from contributors.
vercel.com · GitHub Vercel · Twitter @vercel
I tried to upgrade undici
dependency at packages/primitives
, but any version starting from v5.14.0 is failing:
Node.js v18.14.0
node:internal/errors:490
ErrorCaptureStackTrace(err);
^
TypeError: The "transform.readable" property must be an instance of ReadableStream. Received an instance of ReadableStream
at new NodeError (node:internal/errors:399:5)
at ReadableStream.pipeThrough (node:internal/webstreams/readablestream:365:13)
at fetchFinale (/Users/kikobeats/vercel/edge-runtime/packages/primitives/dist/fetch.js:14275:56)
at mainFetch (/Users/kikobeats/vercel/edge-runtime/packages/primitives/dist/fetch.js:14164:9)
at processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'ERR_INVALID_ARG_TYPE'
}
Current behavior
Invalid uuid generated.
Expected behavior/code
right uuid.
Possible solution
This bug has been fixed at 1.7.6 of webcrypto-core
PeculiarVentures/webcrypto-core@049cd7c
Additional context/screenshots
Add any other context about the problem here. If applicable, add screenshots to help explain.
something like this:
export interface RequestInit {
body?: BodyInit | null;
headers?: HeadersInit;
method?: string;
}
@Kikobeats @javivelasco #34 was closed prematurely as not everything mentioned there was resolved.
➜ cat node_modules/edge-runtime/package.json | jq '.version'
"1.1.0-beta.21"
➜ npx edge-runtime
ƒ => fetch('https://op.panva.cz', { method: 'POST', body: JSON.stringify({}) })
{ [Symbol(async_id_symbol)]: 33,
[Symbol(trigger_async_id_symbol)]: 4 }
ƒ => Uncaught:
{ [TypeError: fetch failed]
cause: [TypeError: define_process_default.nextTick is not a function] }
We are supporting node12 essentially because it's the minimum Node.js version supported by Next.js.
The moment that changes, we can:
Is your feature request related to a problem? Please describe.
We're using an automated license checking tool that requires the license
field in package.json
to be a valid SPDX license expression.
Describe the solution you'd like
Change MPLv2
to MPL-2.0
in all package.json
s.
Describe alternatives you've considered
n/a
Teachability, Documentation, Adoption, Migration Strategy
This will help users with automated license checking tools.
cat node_modules/edge-runtime/package.json | jq '.version'
"1.1.0-beta.22"
const ab = await crypto.subtle.digest('SHA-256', crypto.getRandomValues(new Uint8Array(32)))
console.log(ab instanceof ArrayBuffer)
console.log(ab.constructor)
Despite ab.constructor
showing an ArrayBuffer
, ab instanceof ArrayBuffer
is false.
Trying to follow the CLI docs to run edge-runtime
on my local Node.js 16 environment.
Steps:
example/fetch.js
file.npm -g install edge-runtime
edge-runtime --listen examples/fetch
Observed: the command exits right away
Expected: an HTTP server is started, executing fetch.js
on every request.
Current behavior
With the following TSConfig, a lot of things are missing in the types:
{
"compilerOptions": {
"moduleResolution": "NodeNext",
"module": "NodeNext",
"strict": true,
"useUnknownInCatchVariables": true,
"noImplicitOverride": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": true,
// Explicitly empty lib (no DOM, etc)
"lib": [],
// Only specify types for edge-runtime
"types": ["@edge-runtime/types"]
}
}
Here's a couple things that don't exist. Perhaps I need to include some other types to "lib" but for example addEventListener
exists in DOM but a lot of things that exist in DOM do not exist in the edge-runtime.
Expected behavior
Every Edge Runtime API should to have types exposed properly.
index.mjs
:// index.mjs
import { EdgeRuntime } from 'edge-runtime'
const main = async () => {
try {
const runtime = new EdgeRuntime();
runtime.evaluate(`
const a = Object.create({})
console.log('a --> ', a);
const b = Object.create(null)
console.log('b --> ', b);
`);
} catch(err) {
console.log(`evaluate error: `, err);
}
}
main();
node ./index.mjs
, you can see the error in terminal:evaluate error: evalmachine.<anonymous>:124
var getConstructorName = /* @__PURE__ */ __name((object) => object.constructor.name, "getConstructorName");
TypeError: Cannot read properties of undefined (reading 'name')
at getConstructorName (evalmachine.<anonymous>:124:84)
at formatRaw (evalmachine.<anonymous>:229:29)
at formatValue (evalmachine.<anonymous>:224:16)
at inspect (evalmachine.<anonymous>:346:16)
at format (evalmachine.<anonymous>:196:26)
at Object.log (evalmachine.<anonymous>:571:55)
at evalmachine.<anonymous>:5:15
console.log
should work successfully on objects with null prototype as it does in the browser.
Current behavior
Cannot use edge runtime on vercel. Error message is:
Failed to instantiate edge runtime.
Class extends value undefined is not a constructor or null
Error: Failed to complete request to /api/stream: Error: socket hang up
Expected behavior/code
Should be able to invoke lambda with edge runtime locally using vercel dev
Possible solution
Force resolution to 1.1.0
and it should work just fine.
Additional context/screenshots
I made a repo to reproduce. Main branch has simple installation of vercel
which resolves edge-runtime
and subpackages to 2.0.0, where the bug is.
The branch edge@v1
has forced resolution to 1.1.0
and it runs just fine.
Our TextDecoder polyfill is performing an instanceof comparison
input.buffer instanceof ArrayBuffer // input here is a `Uint8Array` instance
It's returning false when actually it is, so at that level the polyfill isn't accessing the right ArrayBuffer
constructor
Right now @edge-runtime/format
is missing at https://edge-runtime.vercel.sh
If I import the edge runtime, then my process has an uncaught exception, my process exits with no error message and an exit code of 0
.
Reproduction: https://github.com/EndangeredMassa/reproduction-process-exit-behavior
Example:
import { EdgeRuntime } from 'edge-runtime';
throw new Error('intentional break');
It seems that these lines are the cause:
edge-runtime/packages/runtime/src/edge-runtime.ts
Lines 64 to 76 in ccdb203
If you use the formatter with custom symbol, like:
[customInspectSymbol]() {
return JSON.stringify(deepObject) // ugh
}
You are losing formatter capabilities since you have to manually stringify the value by your own.
Ideally, the formatter should be available there:
[customInspectSymbol]({ format }) {
return format(deepObject) // yay
}
Current behavior
Trying to deploy: https://github.com/andreanidouglas/vercel-rust-example
$ vercel
Error: The Edge Function "api/xor" is referencing unsupported modules:
- wasm/pkg/wasm.js: vc-blob-asset:wasm_bg.wasm
the file wasm.js contains the necessary code to load the WASM into the target webpage
and the wasm_bg.wasm is the generated wasm file to be executed
Expected behavior/code
Upload package to edge runtime
Possible solution
Additional context/screenshots
Add any other context about the problem here. If applicable, add screenshots to help explain.
The errors logging through @edge-runtime/primitives/console.js
will be formated, then the error trace becomes one line error string which lost the trace context. it's hard to debug. Wonder if we can tweak here to log more information.
Currently I work around by change this in console primitives so that I could see the original logging.
var error = /* @__PURE__ */ bareError // __name(format(...args) => bareError((...args)), "error");
var log = /* @__PURE__ */ bareLog // __name(format(...args) => bareLog((...args)), "log");
Ideally I can see error log tracing and I don't have to change it
Logging a response throws, eg console.log(new Response("yes"))
throws an error.
import type { NextRequest } from "next/server";
export const config = {
runtime: "experimental-edge",
};
export default async function handler(req: NextRequest) {
await fetch("https://example.com").then((res) => {
console.log(res); // this throws, commenting out this line makes it work
return res.text();
});
return new Response("yea");
}
import type { NextRequest } from "next/server";
export const config = {
runtime: "experimental-edge",
};
export default async function handler(req: NextRequest) {
const response = new Response("yea");
console.log(response); // this throws, commenting out this line makes it work
return response;
}
Both of these throw
error - Error [TypeError]: Cannot delete property 'Symbol(set-cookie)' of #<HeadersList2>
at <unknown> (evalmachine.<anonymous>:114:24)
at Array.forEach (<anonymous>)
at formatValue (evalmachine.<anonymous>:110:19)
at formatProperty (evalmachine.<anonymous>:181:19)
at <unknown> (evalmachine.<anonymous>:155:114)
at Array.map (<anonymous>)
at formatValue (evalmachine.<anonymous>:155:101)
at formatProperty (evalmachine.<anonymous>:181:19)
at <unknown> (evalmachine.<anonymous>:155:114)
at Array.map (<anonymous>)
I believe it's this line which ends up throwing
edge-runtime/packages/format/src/index.ts
Line 103 in e89ddce
Current behavior
Calling "cookies.set" twice on an appdir api route will set only one cookie.
Expected behavior/code
You'll see one "Set-Cookie" with 2 values, however it should be instead 2 "Set-Cookie" with only one value.
Set-Cookie can be repeated as many time as needed in an HTTP response to set multiple cookies.
Possible solution
This comment explains that .append()
shouldn't be used in response-cookies.ts
Additional context/screenshots
I opened this issue in Next.js, it has been closed but I see that the file wasn't modifier in the edge-runtime source code so I think it's better to open it here !
Current behavior
When the jest is run with collectCoverage option set to true and coverageProvider set to 'babel' the actual test run fails with this error:
What is being imported does not really matter - if I remove imports by moving contents of that file in it just fails at something different (same error though).
Expected behavior/code
Tests should run normally without this error.
Possible solution
What I find working is to switch from 'babel' to 'v8', but that may not be the best solution.
Additional context/screenshots
App is in next and Im testing parts of nextjs middleware (NextRequest/NextResponse from "next/server" package). I also made sure that no new Function/eval is being present in third party deps that are being imported during the test.
Node version: 16.18.1
NPM version: 8.19.2
Jest version: 28.1.3
will be glad for any pointers/thoughts/ideas on this matter 💗
Will be glad to include more info
Is your feature request related to a problem? Please describe.
I'm trying to deploy an edge function that uses the stripe-node
package. Despite the name, it is possible to use it in other runtimes, such as Cloudflare workers and Deno. There is however a problem with Vercel edge functions because the Event
API is not supported (see this issue: stripe/stripe-node#1732). An error is thrown whenever the function is invoked.
You can reproduce the issue by deploying and edge function with the following code:
import Stripe from 'stripe';
const stripe = new Stripe(STRIPE_SECRET_KEY, {
apiVersion: '2022-11-15',
httpClient: Stripe.createFetchHttpClient()
});
Describe the solution you'd like
Support the Event Web API, as it is part of WinterCG's Minimum Common Web Platform API proposal.
The CacheStorage is holding all the
A CacheStorage
object represents a name to cache map of its associated global object's:
self.caches // CacheStorage {}
self.caches instanceof CacheStorage // true
You can create a new Cache
namespace there, and it will be an instance:
const cache = await caches.open('my_cache')
cache instanceof Cache // true
Additionally, CF Workers exposes a default
single global cache object:
const cache = caches.default
cache instanceof Cache
This cache is a bit special: Since the spec actually doesn't provide any way to manipulate the cache that backs fetch(), if you put something into it, then fetch() will match that thing.
These constructors are missing right now:
expect(format(new Map([['foo', 'bar']]))).toBe("Map(1) { 'foo' => 'bar' }")
expect(format(new Set([['foo', 'bar']]))).toBe("Set(1) { [ 'foo', 'bar' ] }")
expect(format(new Uint8Array([1, 2, 3]))).toBe("Uint8Array(3) [ 1, 2, 3 ]")
Current behavior
Using NextJS 13.4, using API routes (Pages Folder) in the following folder structure:
pages/api/[...name].jsx
When i try to use the method getAll()
on the route BASE_URL/api/first-segment/second-segment
:
const { searchParams } = new URL(req.url);
const allSegments = searchParams.getAll('name')
the expected return from getAll()
was to be an array like:
[
'first-segment',
'second-segment'
]
This works correct in localhost
and in chrome js console.
However, when pushing to production (edge runtime), it gives the following code:
[
'first-segment/second-segment',
]
... which is different from the Web API implementation.
Expected behavior/code
From the example above, searchParams.getAll(param)
was expected to return an array with two items. It returned one array with only one item.
It's implemented in two places:
Ideally, we want to move the implementation and tests in a separate package and use it.
Hello! I'm trying to integrate with edge-runtime into my project monorepo, but I'm having a few issues getting started with the types package. When I follow the instructions on the website, I end up with undefined values for Request, CryptoKey, and other Edge Runtime items.
I tracked it down to having "lib": ["ES2021"]
in my tsconfig.json
, but removing it seems to let Node primitives bubble up. Should I be using the default lib
in my TS config to mimic an edge runtime context?
Current behavior
A clear and concise description of the behavior.
I have a minimum reproduction of the issue I am facing here: https://github.com/michealroberts/vercel-trpc-prisma
Essentially, I am trying to run a tRPC server on the vercel edge runtime (as given here: https://trpc.io/docs/fetch#vercel-edge-runtime) from a starter repo here https://github.com/trpc/trpc/tree/main/examples/vercel-edge-runtime by @KATT AND @QuiiBz.
I have managed to get it running locally by hard-setting the prisma datasource to a prisma studio proxy connection as shown here:
I have since tried to replace the datasource with my hardset proxy URL with process.env.DATABASE_URL
as follows:
import { PrismaClient } from '@prisma/client/edge'
export const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABSE_URL
}
}
})
But, alas, it does not work (with an exit code 1):
Expected behavior/code
The expected behaviour would be once added any environment variables to .env
in the project root, they should be injected into the runtime? Unless there is another way to inject process.env variables when running the edge-runtime server locally that I have missed?
Current behavior
Created a blank project to test middleware
> Success! Build completediming config:load:flatten Completed in 3ms
> Ready! Available at http://localhost:3000
but upon accessing localhost:3000, the page returns "This Edge Function has crashed", and the console logs
Failed to instantiate edge runtime.fig:load:flatten Completed in 3ms
__dirname is not defined
Expected behavior/code
The middleware function to run instead of returning page crash
Possible solution
Additional context/screenshots
Repro by running npm run ddev
I don't believe this is a duplicate of #209 since I've tried running with [email protected] and also downgrading to a version of vercel cli that was using [email protected] and received the same errors
It seems as if the @edge-runtime/jest-environment
package does not define the EdgeRuntime
global.
This prevents me from addressing the runtime in unit tests, which should normally work using
if (typeof EdgeRuntime !== 'string') {
// dead-code elimination is enabled for the code inside this block
}
https://edge-runtime.vercel.sh/features/available-apis#addressing-the-runtime
Hey! Working on writing some middleware functions and I suddenly started getting TypeError: Immutable
After some detective work, I found out it's because of the above 3 lines that try to delete these 3 headers when doing a redirection. When I delete these 3 lines locally, everything works as expected. Any idea what these 3 do or why this is happening?
I also understand this hasn't been changed in quite some time, and so it might be something else that's causing this to happen under the hood, I just don't understand it enough and some guidance would be amazing.
I'm on vercel cli 28.4.8.
How to deploy to Vercel, assume that I already have index.js that running the server via `const server = await runServer({ runtime })
I did try
vercel deploy
I don't know if I have to do some custom configuration on build config or something else. If someone know please clarify me this please thank you
NOTE: that it work completely fine on my local-machine
Thank you
The abort-controller polyfill used in edge-runtime isn't compliant with the spec right now, because:
AbortSignal.abort
is missingAbortSignal.timeout
is missingAlternatives:
Related:
Current behavior
When using @edge-runtime/jest-environment
, crypto.randomUUID()
generates an invalid UUID (only 35 characters)
repro: https://github.com/keyz/vercel-edge-runtime-vm-uuid-bug-repro
Expected behavior/code
A valid v4 UUID gets generated per spec
ƒ => new URL('https://example.com')
URL { }
ƒ => const url = new URL('https://example.com')
undefined
ƒ => url
URL { }
ƒ =>
Expected behavior/code
> new URL('https://example.com')
URL {
href: 'https://example.com/',
origin: 'https://example.com',
protocol: 'https:',
username: '',
password: '',
host: 'example.com',
hostname: 'example.com',
port: '',
pathname: '/',
search: '',
searchParams: URLSearchParams {},
hash: ''
}
Current behavior
Cookies are only stored in map by name, so same name cookie will be droped.
Expected behavior/code
Get all cookies by name with different paths.
And the order of cookies should be kept.
Hi, I've been experimenting with edge-runtime using Next 12.2's Edge Server-Rendering with Vercel and have been experiencing some performance issues.
The application itself is very simple, just outputting "Hello World" from the index page in Next.js (see code below)
// pages/index.js
export default function Home() {
return (
<>
Hello World!
</>
)
}
When loading this page via Vercel, I'm seeing response times ranging from 200-400ms, which in itself seems to be slower than I would expect.
This level of performance is consistent unless I repeatedly refresh the page, at which point response times begin to drop to 50-70ms, although this is sporadic and not very consistent.
I'm curious to know whether there is a real issue somewhere or whether I'm just doing something wrong.
You can find the deployed example application here, https://my-app-mike183.vercel.app/
Happy to share any further debug information that you might need 🙂
We can enable users to have simpler tests by having expectations that match the standard library we provide. For instance, Response
matchers:
expect(response).toHaveStatusCode(...);
// These expectations can be shared with `Request` too:
expect(response.headers).toMatchHeaders({ ... });
await expect(response).toHaveJsonBody({ ... });
await expect(response).toHaveTextBody("...");
// or in a single line
await expect(response).toMatchResponse({
status: ...,
headers: { ... },
text: "{ ... }",
json: {}
});
// streams?
await expect(response.body).toEmitChunk(new Uint8Array([...]));
Steps to reproduce / minimal reproducible example:
Result:
The following error occurs in logs either at step 4 or 5:
Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. This is a limitation of Cloudflare Workers which allows us to improve overall performance.
at lib/middleware/plugins/always-repro.ts:34:6
at
at lib/middleware/plugins/always-repro.ts:21:11
at lib/middleware/plugins/always-repro.ts:15:37
at lib/middleware/index.ts:12:46
Home page may fail to load with "Edge middleware failed" error screen.
Expected:
Response is written into function logs each time, home page is loaded every time.
Why is this important:
Using signal is the preferred way to specify timeout for fetch requests from performance point of view and is a part of out of the box JS functionality.
Some notes:
Issue happens when executing logic from lib\middleware\plugins\always-repro.ts. It initializes an abort controller:
private abortController = new AbortController();
which is being used to set up timeout for fetch call:
if (this.timeout) {
abortTimeout = setTimeout(() => {
this.abortController.abort();
}, this.timeout);
}
fetch(this.endpoint, {
method: "POST",
signal: this.abortController.signal,
})
if timeout is not set, however, the issue still occurs. Passing the signal value into fetch is enough:
signal: this.abortController.signal,
The repro example contains two 'plugins' for showcase: always-repro (issue is reproduced always when active) and maybe-repro (issue doesn't appear to occur when active). Their logic is virtually the same, with one small difference: AbortController in always-repro is defined as a class field, while in maybe-repro it is defined in request method scope. If the issue actually doesn't occur with maybe-repro, then perhaps the root cause is in the way the memory is managed and fields are being read.
To switch between them and see the behavior of the other plugin:
While trying to move some of our API routes to the Edge runtime (as encouraged by Vercel), we faced this error during the Vercel build:
too_many_edge_functions_bindings: The Edge Function "api/test" contains too many environment variables + WASM bindings (limit=64, contains=65).
I couldn't find this limit documented anywhere, so did I miss it?
Here's more detail for other devs facing this error.
In our current setup, we have a shared env.ts
file that reads all the env variables on startup and ensure they are correctly set. They are then exposed in a type-safe way. In this file, we have indeed more than 64 entries and removing some of them fixed this error. However, this limitation means that we would need to change the way we access env variables if we want to switch a route to the Edge Runtime.
Current behavior
My Vercel project — https://static-site-omega.vercel.app/ — has a middleware.js
file. For some reason, when that file is in use, some pages run the Cloudflare email obfuscation script, email-decode.min.js
, even though there’s nothing in my code or site config that should invoke this. As of this report, the pages that run the script are:
https://static-site-omega.vercel.app/posts/2020/06/o-say-can-you-ci-cd/
https://static-site-omega.vercel.app/posts/2020/09/mixed-nuts-2020-09/
https://static-site-omega.vercel.app/posts/2020/09/ignition-sequence-start/
https://static-site-omega.vercel.app/posts/2020/10/forward-paas/
https://static-site-omega.vercel.app/posts/2021/09/reply-to-links-feeds/
https://static-site-omega.vercel.app/posts/2021/10/gems-in-rough-10/
https://static-site-omega.vercel.app/posts/2022/03/using-dart-sass-hugo-sequel/
https://static-site-omega.vercel.app/posts/2022/05/using-dart-sass-hugo-github-actions-edition/
https://static-site-omega.vercel.app/posts/2022/06/get-good-git-info-hugo/
https://static-site-omega.vercel.app/posts/2022/06/static-mastodon-toots-hugo/
https://static-site-omega.vercel.app/posts/2022/08/static-embeds-eleventy/
https://static-site-omega.vercel.app/posts/2022/08/static-mastodon-toots-astro/
https://static-site-omega.vercel.app/posts/2023/01/another-move-mastodon/
https://static-site-omega.vercel.app/posts/2023/02/still-another-move-mastodon/
https://static-site-omega.vercel.app/posts/2023/03/headers-up-vercel-edition/
https://static-site-omega.vercel.app/posts/2023/03/reluctant-return-twitter/
Edit: As of 2023-03-23, the stricken-through items no longer have the problem (perhaps due to edits in the pages since then); however, I've added a later-posted page which does have it.
Here is a sample of browser source code showing where it appears in each of these. Note that it appears prior to my own script for email obfuscation. My script is the same on each of the nearly 300 posts on the site, but my testing showed that only the pages listed above are injecting the Cloudflare code prior to my script.
<div class="contactBtn" data-pagefind-ignore>
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
<script nonce="NGQ4ZGFmZTBjNQ/OTUyY2IxNzNiZTgxYjI=">
// The nonce is dynamically generated by the middleware file.
var email64Link="aHJlZj0ibWFpbHRvOmJ3QGJyeWNld3JheS5jb20=";document.write("<a "+atob(email64Link)+'?subject=“Still another move on Mastodon”">')
</script>
Expected behavior/code
The email-decode.min.js
file would not be part of the page load.
Possible solution
Unknown, although I assume it’s somehow related to the fact that Edge Functions and Edge Middleware use Cloudflare Workers.
Additional context/screenshots
middleware.js
, the Cloudflare script doesn’t appear.vercel.app
version of each listed page.@
character within the body copy of each page, although in most cases it’s not even related to email (e.g., it can be in a code block from a GitHub Action wherein there’s a line like uses: actions/checkout@v3
, or in a reference to a Mastodon handle such as @[email protected]
). This seems to be the only thing they each have in common. What’s even odder is that there are other files with @
in the body copy which don’t exhibit this behavior, so the triggering mechanism — if that’s it — doesn’t “work” consistently. Also, notice what happens if you turn off JavaScript on https://static-site-omega.vercel.app/posts/2023/03/reluctant-return-twitter/ — a Mastodon handle is rendered with an [email protected]
warning.https://static-site-omega.vercel.app/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js
. . . even though there is no cdn-cgi
subdirectory in my actual output (e.g., https://vercel.com/brycewray/static-site/4zMoAHehYKPdGweAH8H36Ks7HAt6/source).
middleware.js
file is at https://github.com/brycewray/hugo-site/blob/main/.deprecated/middleware.js (keeping it in .deprecated
until this is resolved, at which time I’ll restore it to the top level).replace
statement in the middleware.js
file to eliminate the script from appearing in the HTML, but this only made the [email protected]
warning show up as if the script were still there but being blocked. This further suggests it’s somehow being injected during the deployment.Here is the GitHub Action (not currently in https://github.com/brycewray/hugo-site/tree/main/.github/workflows while this issue remains unresolved):
name: Deploy to Vercel
# To do a push without triggering this GHA, include one of
# the following in the **commit message**
# (INCLUDING the brackets AND case-sensitivity):
#
# [skip ci]
# [ci skip]
# [no ci]
# [skip actions]
# [actions skip]
#
# “Alternatively, you can end the commit message
# with two empty lines followed by either
# `skip-checks: true` or `skip-checks:true`.”
#
#
# ref: https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs
on:
push:
branches:
- main
env:
HUGO_VERSION: 0.111.3 # will get Extended Version below
DART_SASS_VERSION: 1.59.3
PAGEFIND_VERSION: 0.12.0
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: Checkout default branch
uses: actions/checkout@v3
with:
fetch-depth: 0
# Fetch **all** history (not just deploy commit) for Hugo's .GitInfo and .Lastmod
# See https://discourse.gohugo.io/t/problems-with-gitinfo-in-ci/22480
- name: Download Hugo
run: wget https://github.com/gohugoio/hugo/releases/download/v${{ env.HUGO_VERSION }}/hugo_extended_${{ env.HUGO_VERSION }}_linux-amd64.deb -O hugo_extended_${{ env.HUGO_VERSION }}_linux-amd64.deb
# 0.103.0 began new naming convention
- name: Install Hugo
run: sudo dpkg -i hugo*.deb
- name: Download Embedded Dart Sass
run: curl -LJO https://github.com/sass/dart-sass-embedded/releases/download/${{ env.DART_SASS_VERSION }}/sass_embedded-${{ env.DART_SASS_VERSION }}-linux-x64.tar.gz
- name: Unpack Embedded Dart Sass
run: |
tar -xvf sass_embedded-${{ env.DART_SASS_VERSION }}-linux-x64.tar.gz
sass_embedded/dart-sass-embedded --version
- name: Add Embedded Dart Sass to the PATH
run: echo "$GITHUB_WORKSPACE/sass_embedded" >> $GITHUB_PATH
- name: Install Pagefind
uses: supplypike/setup-bin@v3
with:
uri: "https://github.com/CloudCannon/pagefind/releases/download/v${{ env.PAGEFIND_VERSION }}/pagefind_extended-v${{ env.PAGEFIND_VERSION }}-x86_64-unknown-linux-musl.tar.gz"
name: "pagefind_extended"
version: ${{env.PAGEFIND_VERSION}}
- name: Build site with Hugo
run: hugo --verbose --minify
- name: Move "excerpts" feeds (RSS/Atom and JSON)
run: |
mv public/posts/index.xml public/index-excerpts.xml
mv public/posts/index.json public/index-excerpts.json
- name: Move Vercel-specific files to `/public`
run: |
mv middleware.js public/middleware.js
mv vercel.json public/vercel.json
- name: Run Pagefind
run: pagefind_extended --source "public"
- name: Publish to Vercel (Betahuhn)
uses: BetaHuhn/deploy-to-vercel-action@v1
with:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN_STATIC_SITE }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID}}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID}}
WORKING_DIRECTORY: 'public'
# - name: Publish to Vercel (amondnet)
# uses: amondnet/vercel-action@v20 #deploy
# with:
# vercel-token: ${{ secrets.VERCEL_TOKEN_STATIC_SITE }}
# github-token: ${{ secrets.GITHUB_TOKEN }}
# # vercel-args: '--prod' # optional
# vercel-org-id: ${{ secrets.VERCEL_ORG_ID}}
# vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID}}
# working-directory: 'public'
- name: Remove Vercel-specific files from build
run: |
rm -rf public/middleware.js
rm -rf public/vercel.json
The following code taken from the example docs works on version 2.1.4
but not on version 2.2.0
.
import { EdgeRuntime } from "edge-runtime";
const initialCode = `
addEventListener('fetch', event => {
const { searchParams } = new URL(event.request.url)
const url = searchParams.get('url')
return event.respondWith(fetch(url))
})`;
const edgeRuntime = new EdgeRuntime({ initialCode });
const response = await edgeRuntime.dispatchFetch("https://example.com");
// If your code logic performs asynchronous tasks, you should await them.
// https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil
await response.waitUntil();
When running on version 2.2.0
I get the error:
TSError: ⨯ Unable to compile TypeScript:
cli2.ts:10:39 - error TS2345: Argument of type '{ initialCode: string; }' is not assignable to parameter of type 'EdgeVMOptions<EdgeContext>'.
Object literal may only specify known properties, and 'initialCode' does not exist in type 'EdgeVMOptions<EdgeContext>'.
10 const edgeRuntime = new EdgeRuntime({ initialCode });
~~~~~~~~~~~
cli2.ts:12:36 - error TS2339: Property 'dispatchFetch' does not exist on type 'EdgeVM<EdgeContext>'.
12 const response = await edgeRuntime.dispatchFetch("https://example.com");
~~~~~~~~~~~~~
at createTSError (/Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/index.ts:859:12)
at reportTSError (/Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/index.ts:863:19)
at getOutput (/Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/index.ts:1077:36)
at Object.compile (/Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/index.ts:1433:41)
at transformSource (/Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/esm.ts:400:37)
at /Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/esm.ts:278:53
at async addShortCircuitFlag (/Users/oscar/Library/pnpm/global/5/.pnpm/[email protected]_@[email protected][email protected]/node_modules/ts-node/src/esm.ts:409:15)
at async nextLoad (node:internal/modules/esm/loader:173:22)
at async ESMLoader.load (node:internal/modules/esm/loader:616:20)
at async ESMLoader.moduleProvider (node:internal/modules/esm/loader:472:11) {
diagnosticCodes: [ 2345, 2339 ]
}
If I disable typechecking I get the following error proving that the Typescript error is valid:
TypeError: edgeRuntime.dispatchFetch is not a function
at file:///Users/oscar/Desktop/saas-starter2/cli2.ts:14:36
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:541:24)
at async importModuleDynamicallyWrapper (node:internal/vm/module:438:15)
I would expect this code to still work but if the arguments have changed it would be good if the documentation could be updated.
Context of your question
I feel like vm
module is not secure enough to allow running arbitrary code and would like to ask, why didn't you instead opt-in for v8 isolates like Deno did?
I installed the edge-runtime into an existing project using npm i -D edge-runtime
.
When I then run npx edge-runtime --help
the REPL starts instead of the help showing up as documented here https://edge-runtime.vercel.app/cli#usage
The same thing happens when I install edge-runtime
globally using yarn global add edge-runtime
The following fails in the edge runtime (but not in the node runtime)
class Foo {
constructor() {
...
}
...
}
const cls = Foo;
cls instanceof Function // true in node runtime, false in edge runtime
Encountered when using the Firebase Client SDK while initializing the auth module where it tries to discern if a passed argument is a class or not.
I am trying to dynamically import a function with the filename given in a function argument.
This are my approaches and outcomes:
First approach: require()
Line of Code:
const file = await require(`./${fileName}`);
And the compiler options:
"module": "ESNext",
"target": "CommonJS",
"esModuleInterop": true,
This is giving me this error:
ReferenceError: require is not defined
at (api/test.js:116:87)
at (api/test.js:116:24)
at (api/test.js:130:28)
However, when i trying the same with an static path and not the variable in the path, it works, no errors.
const file = await require('./test');
Second approach: import()
Line of Code:
const file = await import(`./${fileName}`);
const file = await import('./test');
And my typescript compiler options:
"module": "es2020",
"target": "es2020",
"esModuleInterop": true,
But that is giving me this error, with the variable in the path and also without.
Error: internal error
at (api/test.js:87:52)
at (api/test.js:101:34)
at (api/test.js:23:11)
Current behavior
Consider the following code to be run inside EdgeRuntime
import * as Y from "yjs";
addEventListener("fetch", (event) => {
console.log(Y);
return event.respondWith(new Response("hello world"));
});
All it does is import the yjs library and log it.
Now, we have a separate script that actually bundles it and runs it:
import { EdgeRuntime } from "edge-runtime";
import * as esbuild from "esbuild";
// bundle the code in initialCode.js
const initialCode = esbuild.buildSync({
entryPoints: ["./initialCode.js"],
bundle: true,
write: false,
format: "esm",
target: "es2019",
// minify: true, // uncommenting this line "fixes" the issue
}).outputFiles[0].text;
const runtime = new EdgeRuntime({
initialCode,
});
const response = await runtime.dispatchFetch("https://example.com");
await response.waitUntil();
This throws the following error:
evalmachine.<anonymous>:6991
throw new TypeError("Failed to parse URL from " + input, { cause: err });
^
TypeError: Failed to parse URL from https://example.com
at new Request (evalmachine.<anonymous>:6991:19)
at EdgeRuntime.dispatchFetch (evalmachine.<anonymous>:2:21)
at file:///Users/threepointone/code/edge-runtime-bug/index.mjs:17:32
at ModuleJob.run (node:internal/modules/esm/module_job:194:25) {
[cause]: RangeError: Invalid code point NaN
at Function.fromCodePoint (<anonymous>)
at new URLStateMachine (evalmachine.<anonymous>:1533:49)
at module2.exports.basicURLParse (evalmachine.<anonymous>:2100:19)
at new URLImpl (evalmachine.<anonymous>:2825:31)
at exports.setup (evalmachine.<anonymous>:3020:16)
at new URL (evalmachine.<anonymous>:3074:26)
at new Request (evalmachine.<anonymous>:6989:25)
at EdgeRuntime.dispatchFetch (evalmachine.<anonymous>:2:21)
at file:///Users/threepointone/code/edge-runtime-bug/index.mjs:17:32
at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
}
The workaround for this is to enable minify:true
when bundling, and that makes the code work as expected.
Now, I'm not certain whether this is a bug with yjs, esbuild, or edge-runtime, but I suspect it's edge-runtime, because importing yjs in node works fine, as well as when it's bundled with esbuild. It's only when trying to import it inside edge-runtime that the error pops up. The stack trace implies an error with the url, which doesn't seem right.
Expected behavior/code
The code doesn't crash.
Additional context/screenshots
I made a sample repo that reproduces the bug as described above - https://github.com/threepointone/edge-runtime-bug
There are some typos on the docs, here they are:
diff --git a/docs/pages/packages/feature-detector.mdx b/docs/pages/packages/feature-detector.mdx
index 051eae6..747f585 100644
@@ -5,7 +5,7 @@ import { Tabs, Tab } from '../../components/tabs'
The **@edge-runtime/feature-detector** package contains utilities to analyze code running on the edge and its used low-level APIs.
-It leverages the excellent [ts-morph](https://ts-morph.com/) package, which is a wrapper around TypeScript compiler API to navigate its Abstract Syntaxt Tree (AST).
+It leverages the excellent [ts-morph](https://ts-morph.com/) package, which is a wrapper around TypeScript compiler API to navigate its Abstract Syntax Tree (AST).
It can analyse JavaScript and TypeScript code.
diff --git a/docs/pages/packages/format.mdx b/docs/pages/packages/format.mdx
index 757d9e7..facdb04 100644
@@ -108,6 +108,6 @@ The default behavior is `error.toString()`.
##### customInspectSymbol?: symbol
-It sets the symbold to be used for priting custom behavior.
+It sets the symbol to be used for printing custom behavior.
The default value is `edge-runtime.inspect.custom`.
diff --git a/docs/pages/packages/node-utils.mdx b/docs/pages/packages/node-utils.mdx
index 9d7850d..3c6d0a3 100644
@@ -110,14 +110,14 @@ It needs globals Web contstructor a [dependencies](#dependencies-object), as wel
Builds a transformer function to build a fetch event from a web [Request].
The returned event is linked to provided request, and has a mocked [waitUntil()](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) method, which throws on access.
-It needs globals Web contstructor a [dependencies](#dependencies-object).
+It needs globals Web constructor a [dependencies](#dependencies-object).
### toOutgoingHeaders(headers: Headers): OutgoingHttpHeaders
Turns Web [Request.headers](https://developer.mozilla.org/en-US/docs/Web/API/Request/headers) into
Node.js `ServerResponse` [OutgoingHttpHeaders](https://nodejs.org/api/http.html#responsegetheaders).
-Includes `set-cookie` special handling, spliting multiple values when relevant.
+Includes `set-cookie` special handling, splitting multiple values when relevant.
### buildToHeaders(dependencies): toHeaders(nodeHeaders: IncomingHttpHeaders): Headers
diff --git a/docs/pages/packages/ponyfill.mdx b/docs/pages/packages/ponyfill.mdx
index 5ca31fc..9c05499 100644
@@ -7,7 +7,7 @@ The **@edge-runtime/ponyfill** package helps to have the Edge Runtime APIs avail
- When running on Edge Runtime, no polyfills will be loaded, and the native implementations will be used.
- When running on Node.js runtimes, this package will load the polyfills from [@edge-runtime/primitives](/packages/primitives).
-Note this is just necessary if you want to run the same code accross diferent environments.
+Note this is just necessary if you want to run the same code across different environments.
diff --git a/docs/pages/packages/primitives.mdx b/docs/pages/packages/primitives.mdx
index 4ab6ca0..95320cd 100644
@@ -6,7 +6,7 @@ The **@edge-runtime/primitives** package contains all the Web Standard APIs that
These APIs are a subset of modern browser APIs (such as `fetch`, `URLPattern`, `structuredClone`, etc).
-See full list is availabe at [Edge Runtime APIs](/features/available-apis).
+See full list is available at [Edge Runtime APIs](/features/available-apis).
## Installation
I think having a public method to expose "hot reloading" is useful.
Generally speaking this kind of sandboxes are great to implement great developer experience where the developer simply write code and have it executed and hot reloaded in the same "context" of an edge runtime.
So i think edge runtime is missing a method to hot reload the developer code.
Now i'm using this workaround but rely on internals and isn't so good:
import { EdgeRuntime, runServer } from 'edge-runtime'
async function main() {
const initialCode = `
addEventListener('fetch', event => {
console.log('Call Fetch')
return event.respondWith(new Response('Hello'))
})`
const runtime = new EdgeRuntime({ initialCode })
const server = await runServer({ runtime, port: 9000 })
console.log('Listeing on', server.url)
let i = 0
// In real world this is an hook from a compilation step
setInterval(() => {
// WORKAROUND
runtime.evaluate(`
delete self.__listeners['fetch'];
`)
runtime.evaluate(`
addEventListener('fetch', event => {
console.log('Call Fetch ' + ${i})
return event.respondWith(new Response('Hello ${i}'))
})`)
i++
}, 1000)
}
main().catch((err) => {
console.error(err)
})
Having a file run is not working with the latest betas. some.mjs
in my example does just console.log('foo')
✗ npm i [email protected]
✗ npx edge-runtime some.mjs
foo
✗ npm i [email protected]
✗ npx edge-runtime some.mjs
Error: Cannot find module 'tr46'
Require stack:
- /repo/node_modules/@edge-runtime/vm/dist/edge-vm.js
- /repo/node_modules/@edge-runtime/vm/dist/index.js
- /repo/node_modules/edge-runtime/dist/edge-runtime.js
- /repo/node_modules/edge-runtime/dist/cli/index.js
at Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
at Module._load (node:internal/modules/cjs/loader:804:27)
at Module.require (node:internal/modules/cjs/loader:1022:19)
at require (node:internal/modules/cjs/helpers:102:18)
at addPrimitives (/repo/node_modules/@edge-runtime/vm/dist/edge-vm.js:79:37)
at Object.extend (/repo/node_modules/@edge-runtime/vm/dist/edge-vm.js:17:38)
at new VM (/repo/node_modules/@edge-runtime/vm/dist/vm.js:23:92)
at new EdgeVM (/repo/node_modules/@edge-runtime/vm/dist/edge-vm.js:13:9)
at new EdgeRuntime (/repo/node_modules/edge-runtime/dist/edge-runtime.js:18:9)
at main (/repo/node_modules/edge-runtime/dist/cli/index.js:37:21) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/repo/node_modules/@edge-runtime/vm/dist/edge-vm.js',
'/repo/node_modules/@edge-runtime/vm/dist/index.js',
'/repo/node_modules/edge-runtime/dist/edge-runtime.js',
'/repo/node_modules/edge-runtime/dist/cli/index.js'
]
}
Edit: likewise, globals are missing in REPL
➜ ✗ npx edge-runtime
ƒ => fetch
Uncaught ReferenceError: fetch is not defined
ƒ => crypto
Uncaught ReferenceError: crypto is not defined
ƒ => atob
Uncaught ReferenceError: atob is not defined
ƒ => btoa
Uncaught ReferenceError: btoa is not defined
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.