Skip to content

Commit

Permalink
Merge pull request #48 from jridgewell/textdecoder-bug
Browse files Browse the repository at this point in the history
fix: make `Uint8Array` available for `TextDecoder`
  • Loading branch information
Kikobeats committed Jul 27, 2022
2 parents 5a305c7 + a4ee6b4 commit 50bdb9f
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 150 deletions.
12 changes: 12 additions & 0 deletions packages/primitives/tests/encoding.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { TextDecoder } from '../encoding'

test('TextDecoder', () => {
const input = new Uint8Array([
101, 100, 103, 101, 45, 112, 105, 110, 103, 46, 118, 101, 114, 99, 101, 108,
46, 97, 112, 112,
])

const utf8Decoder = new TextDecoder('utf-8', { ignoreBOM: true })
const output = utf8Decoder.decode(input)
expect(output).toBe('edge-ping.vercel.app')
})
7 changes: 7 additions & 0 deletions packages/primitives/tests/url.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { URL } from '../url'

test('URL', async () => {
const url = new URL('https://edge-ping.vercel.app/')
expect(typeof url).toBe('object')
expect(url.toString()).toBe('https://edge-ping.vercel.app/')
})
22 changes: 14 additions & 8 deletions packages/vm/src/edge-vm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,20 @@ function addPrimitives(context: VMContext) {
exports: requireWithCache({
context,
path: require.resolve('@edge-runtime/primitives/console'),
scopedContext: { console: console },
scopedContext: { console },
}),
nonenumerable: ['console'],
})

const encodings = requireWithCache({
context,
path: require.resolve('@edge-runtime/primitives/encoding'),
scopedContext: { Buffer, global: { ArrayBuffer } },
})

// Encoding APIs
defineProperties(context, {
exports: requireWithCache({
context,
path: require.resolve('@edge-runtime/primitives/encoding'),
scopedContext: { Buffer },
}),
exports: encodings,
nonenumerable: ['atob', 'btoa', 'TextEncoder', 'TextDecoder'],
})

Expand Down Expand Up @@ -144,6 +146,10 @@ function addPrimitives(context: VMContext) {
cache: new Map([['punycode', { exports: require('punycode') }]]),
context,
path: require.resolve('@edge-runtime/primitives/url'),
scopedContext: {
TextEncoder: encodings.TextEncoder,
TextDecoder: encodings.TextDecoder,
},
}),
nonenumerable: ['URL', 'URLSearchParams', 'URLPattern'],
})
Expand Down Expand Up @@ -186,8 +192,8 @@ function addPrimitives(context: VMContext) {
return { register: function () {} }
},
global: {},
queueMicrotask: queueMicrotask,
setImmediate: setImmediate,
queueMicrotask,
setImmediate,
},
})

Expand Down
288 changes: 146 additions & 142 deletions packages/vm/tests/unit/edge-vm.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,151 @@
import { EdgeVM } from '../../src'

test('preload web standard APIs', () => {
const edgeVM = new EdgeVM()
edgeVM.evaluate('this.headers = new Headers()')
edgeVM.evaluate(
"this.request = new Request('https://edge-ping.vercel.app', { headers: new Headers({ 'Content-Type': 'text/xml' }) })"
)
describe('preload web standard APIs', () => {
describe('TextDecoder', () => {
it('with Uint8Array', () => {
const edgeVM = new EdgeVM()
edgeVM.evaluate(
"this.decode = new TextDecoder('utf-8', { ignoreBOM: true }).decode(new Uint8Array([101,100,103,101,45,112,105,110,103,46,118,101,114,99,101,108,46,97,112,112 ]))"
)
expect(edgeVM.context.decode).toBe('edge-ping.vercel.app')
})

it('supports a vary of encodings', async () => {
const encodings = [
'ascii',
'big5',
'euc-jp',
'euc-kr',
'gb18030',
'gbk',
'hz-gb-2312',
'ibm866',
'iso-2022-jp',
'iso-2022-kr',
'iso-8859-1',
'iso-8859-2',
'iso-8859-3',
'iso-8859-4',
'iso-8859-5',
'iso-8859-6',
'iso-8859-7',
'iso-8859-8',
'iso-8859-8i',
'iso-8859-10',
'iso-8859-13',
'iso-8859-14',
'iso-8859-15',
'iso-8859-16',
'koi8-r',
'koi8-u',
'latin1',
'macintosh',
'shift-jis',
'utf-16be',
'utf-16le',
'utf8',
'windows-874',
'windows-1250',
'windows-1251',
'windows-1252',
'windows-1253',
'windows-1254',
'windows-1255',
'windows-1256',
'windows-1257',
'windows-1258',
'x-mac-cyrillic',
'x-user-defined',
]

const vm = new EdgeVM()
const supported: string[] = []
const notSupported: string[] = []

encodings.forEach((encoding) => {
try {
vm.evaluate(`new TextDecoder('${encoding}')`)
supported.push(encoding)
} catch (error) {
notSupported.push(encoding)
}
})

expect(supported).toEqual(
expect.arrayContaining([
'ascii',
'big5',
'euc-jp',
'euc-kr',
'gb18030',
'gbk',
'ibm866',
'iso-2022-jp',
'iso-8859-1',
'iso-8859-2',
'iso-8859-3',
'iso-8859-4',
'iso-8859-5',
'iso-8859-6',
'iso-8859-7',
'iso-8859-8',
'iso-8859-10',
'iso-8859-13',
'iso-8859-14',
'iso-8859-15',
// "iso-8859-16",
'koi8-r',
'koi8-u',
'latin1',
'macintosh',
'shift-jis',
'utf-16be',
'utf-16le',
'utf8',
'windows-874',
'windows-1250',
'windows-1251',
'windows-1252',
'windows-1253',
'windows-1254',
'windows-1255',
'windows-1256',
'windows-1257',
'windows-1258',
'x-mac-cyrillic',
])
)
})
})

expect(edgeVM.context.headers).toBeTruthy()
expect(edgeVM.context.request).toBeTruthy()
expect(edgeVM.context.request.headers.get('Content-Type')).toEqual('text/xml')
it('URL', () => {
const edgeVM = new EdgeVM()
edgeVM.evaluate("this.url = new URL('https://edge-ping.vercel.app/')")
expect(edgeVM.context.url).toBeTruthy()
})

describe('fetch', () => {
it('parsing to text', async () => {
const html = await new EdgeVM().evaluate(
`fetch('https://example.vercel.sh').then(res => res.text())`
)
expect(html.startsWith('<!doctype html>')).toBe(true)
})

it('with Headers', async () => {
const edgeVM = new EdgeVM()
edgeVM.evaluate('this.headers = new Headers()')
edgeVM.evaluate(
"this.request = new Request('https://edge-ping.vercel.app', { headers: new Headers({ 'Content-Type': 'text/xml' }) })"
)

expect(edgeVM.context.headers).toBeTruthy()
expect(edgeVM.context.request).toBeTruthy()
expect(edgeVM.context.request.headers.get('Content-Type')).toEqual(
'text/xml'
)
})
})
})

test('interact with fetch out of vm', async () => {
Expand Down Expand Up @@ -54,139 +190,7 @@ test('extend a web standard API', async () => {
})
})

it('allows to run fetch', async () => {
const textp = await new EdgeVM().evaluate(
`fetch('https://example.vercel.sh').then(res => res.text())`
)
expect(textp.startsWith('<!doctype html>')).toBe(true)
})

it('TextDecoder works with Uint8Array', async () => {
const buffer = new Uint8Array([
123, 34, 110, 97, 109, 101, 34, 58, 34, 74, 111, 104, 110, 34, 44, 34, 105,
97, 116, 34, 58, 49, 54, 53, 56, 55, 52, 49, 54, 51, 57, 44, 34, 101, 120,
112, 34, 58, 49, 54, 54, 49, 51, 51, 51, 54, 51, 57, 44, 34, 106, 116, 105,
34, 58, 34, 99, 99, 53, 98, 48, 99, 55, 100, 45, 99, 49, 48, 99, 45, 52, 57,
51, 98, 45, 57, 98, 54, 102, 45, 102, 52, 99, 51, 101, 50, 101, 97, 97, 52,
50, 98, 34, 125,
])

const decoded = new TextDecoder().decode(buffer)
expect(JSON.parse(decoded)).toStrictEqual({
name: 'John',
iat: 1658741639,
exp: 1661333639,
jti: 'cc5b0c7d-c10c-493b-9b6f-f4c3e2eaa42b',
})
})

it('TextDecoder supports a vary of encodings', async () => {
const encodings = [
'ascii',
'big5',
'euc-jp',
'euc-kr',
'gb18030',
'gbk',
'hz-gb-2312',
'ibm866',
'iso-2022-jp',
'iso-2022-kr',
'iso-8859-1',
'iso-8859-2',
'iso-8859-3',
'iso-8859-4',
'iso-8859-5',
'iso-8859-6',
'iso-8859-7',
'iso-8859-8',
'iso-8859-8i',
'iso-8859-10',
'iso-8859-13',
'iso-8859-14',
'iso-8859-15',
'iso-8859-16',
'koi8-r',
'koi8-u',
'latin1',
'macintosh',
'shift-jis',
'utf-16be',
'utf-16le',
'utf8',
'windows-874',
'windows-1250',
'windows-1251',
'windows-1252',
'windows-1253',
'windows-1254',
'windows-1255',
'windows-1256',
'windows-1257',
'windows-1258',
'x-mac-cyrillic',
'x-user-defined',
]

const vm = new EdgeVM()
const supported: string[] = []
const notSupported: string[] = []

encodings.forEach((encoding) => {
try {
vm.evaluate(`new TextDecoder('${encoding}')`)
supported.push(encoding)
} catch (error) {
notSupported.push(encoding)
}
})

expect(supported).toEqual(
expect.arrayContaining([
'ascii',
'big5',
'euc-jp',
'euc-kr',
'gb18030',
'gbk',
'ibm866',
'iso-2022-jp',
'iso-8859-1',
'iso-8859-2',
'iso-8859-3',
'iso-8859-4',
'iso-8859-5',
'iso-8859-6',
'iso-8859-7',
'iso-8859-8',
'iso-8859-10',
'iso-8859-13',
'iso-8859-14',
'iso-8859-15',
// "iso-8859-16",
'koi8-r',
'koi8-u',
'latin1',
'macintosh',
'shift-jis',
'utf-16be',
'utf-16le',
'utf8',
'windows-874',
'windows-1250',
'windows-1251',
'windows-1252',
'windows-1253',
'windows-1254',
'windows-1255',
'windows-1256',
'windows-1257',
'windows-1258',
'x-mac-cyrillic',
])
)
})

// TODO: add decoder case
it('uses the same builtins in polyfills as in VM', () => {
expect(
new EdgeVM().evaluate(
Expand Down

1 comment on commit 50bdb9f

@vercel
Copy link

@vercel vercel bot commented on 50bdb9f Jul 27, 2022

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

edge-runtime – ./

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

Please sign in to comment.