Git Product home page Git Product logo

edge-runtime's Introduction

edge-runtime's People

Contributors

adamjmcgrath avatar akitasummer avatar aui avatar await-ovo avatar balazsorban44 avatar dependabot[bot] avatar devjiwonchoi avatar feugy avatar github-actions[bot] avatar ijjk avatar janpot avatar javivelasco avatar jridgewell avatar kikobeats avatar konomae avatar leerob avatar matheuss avatar nkzawa avatar promer94 avatar renchris avatar rezof avatar schniz avatar simon-mathewson avatar smaeda-ks avatar stefanjudis avatar steren avatar styfle avatar sukkaw avatar wyattjoh avatar ykzts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

edge-runtime's Issues

undici v5.14.0 or higher is failing

Bug Report

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'
}

"Failed to instantiate edge runtime.fig:load:flatten", "__dirname is not defined"

Bug Report

Current behavior

Created a blank project to test middleware

Server starts up fine
> 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

Archive.zip

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

ArrayBuffer constructor mismatch, instanceof with the global doesn't work

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.

`Failed to instantiate edge runtime.` on `vercel dev`

Bug Report

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.

https://github.com/y-nk/streaming-at-edge/tree/edge%40v1

Maximum number of env variables

Summary

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.

jest-environment: extend `expect` with custom expectations

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([...]));

docs: Typos

There are some typos on the docs, here they are:

Feature Detector

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.

Format

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`.

Node Utils

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

Ponyfill

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.

Primitives

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

Calling cookies.set twice sets only one value

Bug Report

Current behavior

Calling "cookies.set" twice on an appdir api route will set only one cookie.
221156616-6833d576-2687-43b2-9a13-74ca513f6c15

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 !

Importing Functions from local files with dynamic paths

Bug Report

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)

format null prototyped object throw unexpected error

Step to reproduce:

  1. write code as below in 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();
  1. executing 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

Expected

console.log should work successfully on objects with null prototype as it does in the browser.

Environments

  • node: v16.15.1
  • edge-runtime: 1.1.0-beta.31

fetch POST not working due to missing internals

@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] }

Using `middleware.js` sometimes runs Cloudflare email obfuscation JS

Bug Report

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

  • When I don’t use middleware.js, the Cloudflare script doesn’t appear.
  • The script appears on both the custom-domain version (when I assign one) and the vercel.app version of each listed page.
  • I am guessing from the content of the listed pages that this is somehow being triggered by the presence of the @ 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.
  • According to the headers, the origin of the script is:
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).

  • The repo from which I deploy, via a GitHub Action, is https://github.com/brycewray/hugo-site.
  • The 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).
  • The GitHub Action I use appears at the end of this comment.
  • I did try deploying straight from the Git repo without a GitHub Action — i.e., using the normal deploy method — but still encountered the same oddity concerning the Cloudflare script.
  • I even tried using a 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.
  • [No screenshots]

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

Class is missing Function in prototype chain

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.

cli broken since beta.11

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

importing `edge-runtime` breaks process exit behavior

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:

/**
* Define system-level handlers to make sure that we report to the user
* whenever there is an unhandled rejection or exception before the process crashes.
*/
process.on(
'unhandledRejection',
function invokeRejectionHandlers(reason, promise) {
unhandledRejectionHandlers?.forEach((handler) => handler(reason, promise))
}
)
process.on('uncaughtException', function invokeErrorHandlers(error) {
uncaughtExceptionHandlers?.forEach((handler) => handler(error))
})

Can this deploy on Vercel without nextjs?

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

  • deploy via vercel deploy
    • and I try to navigate to the deployed URL, it gives me 404 (as like my fetch event hasn't ran)

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

Expose a method for hot reloading

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)
})

format: provide formatter inside custom symbol

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
  }

process is not defined

Bug Report

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:

Screenshot 2023-02-15 at 13 50 56

Screenshot 2023-02-15 at 13 51 05

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):

Screenshot 2023-02-15 at 13 52 34

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?

URLSearchParams - getAll() is not returning proper array in edge runtime.

Bug Report

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.

"Cannot perform I/O on behalf of a different request" error when using signal on a fetch call in middleware

Steps to reproduce / minimal reproducible example:

  1. Fork / use https://github.com/art-alexeyenko/lock-stock-mock as minimal repro example;
  2. Deploy mock-express to Vercel - this will be used as an endpoint for fetch;
  3. Deploy next-mid-ts to Vercel, set FETCH_ENDPOINT env variable to to https://{mock-express-vercel-url}/api;
    Optional: set DEBUG env variable to "mock:*"
  4. Check Function logs for next-mid-ts in Vercel;
  5. Open two incognito windows with next-mid-ts homepage, refresh spam both for 10-12 seconds.

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:

  1. Modify next-mid-ts app;
  2. In lib\middleware\index.ts comment lines 4 and 12, uncomment lines 3 and 13;
  3. Redeploy next-mid-ts;
  4. Use the same repro steps (check Function logs/spam home page over short period of time).

Format: add support for some missing constructors

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 ]")

Deleting Headers Causing Immutable TypeErrors

response.headers.delete('content-encoding');

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.

@edge-runtime/types: Missing some types

Current behavior

CleanShot 2022-09-20 at 18 36 11@2x

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.

Problems with inconsistent performance

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 🙂

Use `MPL-2.0` instead of `MPLv2` in `license` field

Feature Request

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.jsons.

Describe alternatives you've considered

n/a

Teachability, Documentation, Adoption, Migration Strategy

This will help users with automated license checking tools.

use `isolated-vm` instead of `vm`

Questions & Answers

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?

Does @edge-runtime/types need additional dependencies or settings?

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?

`new URL` is not being serialized properly

Bug Report

ƒ => 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: ''
}

Error logging lost stack trace

Observed

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.

Workaround

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");

Expected

Ideally I can see error log tracing and I don't have to change it

console.log()'ging a response throws

Logging a response throws, eg console.log(new Response("yes")) throws an error.

Reproduction

First way to reproduce (longer)

  1. Create an Edge API Route
  2. Fetch anything
  3. Log the response
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");
}

Second way to reproduce (shorter)

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;
}

Error

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

delete obj[symbol]

importing `yjs` makes EdgeRuntime crash

Bug Report

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

Cannot use @edge-runtime/jest-environment with collectCoverage: true and coverageProvider: 'babel'

Bug Report

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:
image

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

Primitives: Implement `Cache` as `CacheStorage` interfaces

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.

Runtime 2.2.0 is not working

Bug Report

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.

WASM (rust): is referencing unsupported module

Bug Report

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.

TextDecoder inside VM with Uint8Array from parent

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

Support `Event` Web API

Feature Request

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.