From 9a57fec40189fab08f6692a52b5f8a52604ad50a Mon Sep 17 00:00:00 2001 From: "Thang X. Vu" Date: Tue, 2 Jul 2024 17:00:37 +0700 Subject: [PATCH] fix: remove inline js using `new Function` --- shapes/object.ts | 97 +++++++++++------------------------------------- 1 file changed, 21 insertions(+), 76 deletions(-) diff --git a/shapes/object.ts b/shapes/object.ts index eb7a391..9134297 100644 --- a/shapes/object.ts +++ b/shapes/object.ts @@ -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(key: K, $value: Shape): Shape< @@ -70,7 +80,7 @@ type UnionKeys = T extends T ? keyof T : never export type ObjectMembers = [ ...never extends T ? { [K in keyof T]: AnyShape extends T[K] ? AnyShape - : + : & UnionKeys> & { [L in keyof T]: K extends L ? never : UnionKeys> @@ -98,82 +108,17 @@ export function object(...members: ObjectMembers): Shap } function generateEncode(members: Shape[]) { - 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() - 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[]) { - const vars: string[] = [] - const args: unknown[] = [] - - const valueVisitor = new ShapeVisitor() - 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() - 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); } }