Skip to content

Commit

Permalink
fix: remove inline js using new Function
Browse files Browse the repository at this point in the history
  • Loading branch information
sinzii committed Jul 2, 2024
1 parent a96171a commit 9a57fec
Showing 1 changed file with 21 additions and 76 deletions.
97 changes: 21 additions & 76 deletions shapes/object.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { AnyShape, createShape, Expand, Input, metadata, Output, Shape, ShapeVisitor, U2I } from "../common/mod.ts"
import { constant } from "./constant.ts"
import {
AnyShape,
createShape,
DecodeBuffer,
EncodeBuffer,
Expand,
Input,
metadata,
Output,
Shape,
U2I
} from "../common/mod.ts"
import { option } from "./option.ts"

export function field<K extends keyof any, VI, VO>(key: K, $value: Shape<VI, VO>): Shape<
Expand Down Expand Up @@ -70,7 +80,7 @@ type UnionKeys<T> = T extends T ? keyof T : never
export type ObjectMembers<T extends AnyShape[]> = [
...never extends T ? {
[K in keyof T]: AnyShape extends T[K] ? AnyShape
:
:
& UnionKeys<Input<T[K]>>
& {
[L in keyof T]: K extends L ? never : UnionKeys<Input<T[L]>>
Expand Down Expand Up @@ -98,82 +108,17 @@ export function object<T extends AnyShape[]>(...members: ObjectMembers<T>): Shap
}

function generateEncode(members: Shape<any>[]) {
const vars: string[] = []
const args: unknown[] = []

const valueVisitor = new ShapeVisitor<(v: string) => string>()
valueVisitor.add(constant, (shape, value, pattern) => (v) => {
if (pattern) {
return `${addVar(shape)}.subEncode(buffer, ${v})`
}
return addVar(value)
})
valueVisitor.fallback((shape) => (v) => {
return `${addVar(shape)}.subEncode(buffer, ${v})`
})

const fieldVisitor = new ShapeVisitor<string>()
fieldVisitor.add(field, (_, key, value) => {
return valueVisitor.visit(value)(`value[${typeof key === "symbol" ? addVar(key) : JSON.stringify(key)}]`)
})
fieldVisitor.add(optionalField, (_, key, value) => {
return fieldVisitor.visit(field(key, option(value)))
})
fieldVisitor.add(object, (_, ...members) => {
return members.map((x) => fieldVisitor.visit(x)).join(";")
})
fieldVisitor.fallback((shape) => {
return `${addVar(shape)}.subEncode(buffer, value)`
})

const content = members.map((x) => fieldVisitor.visit(x)).join(";")

return (new Function(...vars, `return function objectEncode(buffer,value){${content}}`))(...args)

function addVar(value: unknown) {
const v = "v" + vars.length
vars.push(v)
args.push(value)
return v
return (buffer: EncodeBuffer, value: any) => {
members.forEach(member => {
member.subEncode(buffer, value);
});
}
}

function generateDecode(members: Shape<any>[]) {
const vars: string[] = []
const args: unknown[] = []

const valueVisitor = new ShapeVisitor<string>()
valueVisitor.add(constant, (shape, value, pattern) => {
if (pattern) {
return `${addVar(shape)}.subDecode(buffer)`
}
return addVar(value)
})
valueVisitor.fallback((shape) => {
return `${addVar(shape)}.subDecode(buffer)`
})
const fieldVisitor = new ShapeVisitor<string>()
fieldVisitor.add(field, (_, key, value) => {
return `[${typeof key === "symbol" ? addVar(key) : JSON.stringify(key)}]: ${valueVisitor.visit(value)}`
})
fieldVisitor.add(optionalField, (_, key, value) => {
return `...buffer.array[buffer.index++] ? {${fieldVisitor.visit(field(key, value))} } : undefined`
})
fieldVisitor.add(object, (_, ...members) => {
return members.map((x) => fieldVisitor.visit(x)).join(",")
})
fieldVisitor.fallback((shape) => {
return `...${addVar(shape)}.subDecode(buffer)`
})

const content = members.map((x) => fieldVisitor.visit(x)).join(",")

return (new Function(...vars, `return function objectDecode(buffer){return{${content}}}`))(...args)

function addVar(value: unknown) {
const v = "v" + vars.length
vars.push(v)
args.push(value)
return v
return (buffer: DecodeBuffer) => {
return members.reduce((o, member) => {
return { ...o, ...member.subDecode(buffer) }
}, {} as any);
}
}

0 comments on commit 9a57fec

Please sign in to comment.