Comparing version
{ | ||
"targets": { | ||
"debug": { | ||
"binaryFile": "build/untouched.wasm", | ||
"textFile": "build/untouched.wat", | ||
"outFile": "build/debug.wasm", | ||
"textFile": "build/debug.wat", | ||
"sourceMap": true, | ||
@@ -10,6 +10,6 @@ "debug": true | ||
"release": { | ||
"binaryFile": "build/optimized.wasm", | ||
"textFile": "build/optimized.wat", | ||
"outFile": "build/release.wasm", | ||
"textFile": "build/release.wat", | ||
"sourceMap": true, | ||
"optimizeLevel": 0, | ||
"optimizeLevel": 3, | ||
"shrinkLevel": 0, | ||
@@ -20,4 +20,3 @@ "converge": false, | ||
"test": { | ||
"binaryFile": "tests/output/test.wasm", | ||
"textFile": "tests/output/test.wat", | ||
"outFile": "build/test.wasm", | ||
"sourceMap": true, | ||
@@ -28,32 +27,8 @@ "optimizeLevel": 0, | ||
"noAssert": false | ||
}, | ||
"bench": { | ||
"binaryFile": "bench/output/bench.wasm", | ||
"textFile": "bench/output/bench.wat", | ||
"sourceMap": true, | ||
"optimizeLevel": 3, | ||
"shrinkLevel": 0, | ||
"converge": false, | ||
"noAssert": false | ||
}, | ||
"dynamic:bench": { | ||
"binaryFile": "dynamic/bench/output/bench.wasm", | ||
"textFile": "dynamic/bench/output/bench.wat", | ||
"sourceMap": true, | ||
"optimizeLevel": 3, | ||
"shrinkLevel": 0, | ||
"converge": false, | ||
"noAssert": false | ||
}, | ||
"dynamic:test": { | ||
"binaryFile": "dynamic/test/output/test.wasm", | ||
"textFile": "dynamic/test/output/test.wat", | ||
"sourceMap": true, | ||
"optimizeLevel": 0, | ||
"shrinkLevel": 0, | ||
"converge": false, | ||
"noAssert": false | ||
} | ||
}, | ||
"options": {} | ||
"options": { | ||
"transform": "./transform", | ||
"bindings": "esm" | ||
} | ||
} |
@@ -1,58 +0,14 @@ | ||
import { StringSink } from 'as-string-sink' | ||
import { DynamicObject } from './DynamicObject' | ||
import { unknown, unknownTypes } from './unknown' | ||
export { unknown, unknownTypes } from './unknown' | ||
export { DynamicObject as Object } from './DynamicObject' | ||
import { StringSink } from "as-string-sink/assembly"; | ||
import { Variant } from "as-variant/assembly"; | ||
import { | ||
backSlashCode, | ||
colonCode, | ||
commaCode, | ||
leftBraceCode, | ||
leftBracketCode, | ||
quoteCode, | ||
rightBraceCode, | ||
rightBracketCode | ||
} from "./chars"; | ||
@global | ||
export class Nullable { } | ||
const quote = '"' | ||
const lbracket = "[" | ||
const rbracket = "]" | ||
const rcbracket = "}" | ||
const lcbracket = "{" | ||
const trueVal = "true" | ||
const falseVal = "false" | ||
const nullVal = "null" | ||
const escapeQuote = '\\"' | ||
const quoteCode: u16 = 34// '"' | ||
const commaCode: u16 = 44// "," | ||
const rbracketCode: u16 = 93// "]" | ||
const lbracketCode: u16 = 91// "[" | ||
const rcbracketCode: u16 = 125// "}" | ||
const lcbracketCode: u16 = 123// "{" | ||
const colonCode: u16 = 58// ":" | ||
const fwd_slashCode: u16 = 92// "/" | ||
const t_charCode: u16 = 116// "t" | ||
const f_charCode: u16 = 116// "t" | ||
const nCode: u16 = 110// "n" | ||
const unknownId = idof<unknown>() | ||
const stringId = idof<string>() | ||
const objectId = idof<DynamicObject>() | ||
const arrayStringId = idof<string[]>() | ||
const arrayBooleanId = idof<boolean[]>() | ||
const arrayBoolId = idof<bool[]>() | ||
const arrayU8Id = idof<u8[]>() | ||
const arrayU16Id = idof<u16[]>() | ||
const arrayU32Id = idof<u32[]>() | ||
const arrayU64Id = idof<u64[]>() | ||
const arrayI8Id = idof<i8[]>() | ||
const arrayI16Id = idof<i16[]>() | ||
const arrayI32Id = idof<i32[]>() | ||
const arrayI64Id = idof<i64[]>() | ||
const arrayF32Id = idof<f32[]>() | ||
const arrayF64Id = idof<f64[]>() | ||
const arrayUnknownId = idof<unknown[]>() | ||
const WS1code = " ".charCodeAt(0) | ||
const WS2code = '\u0020'.charCodeAt(0) | ||
const WS3code = '\u000A'.charCodeAt(0) | ||
const WS4code = '\u000D'.charCodeAt(0) | ||
const WS5code = '\u0009'.charCodeAt(0) | ||
const unknownTrue = unknown.wrap(true) | ||
const unknownFalse = unknown.wrap(false) | ||
const unknownNull = unknown.wrap(null) | ||
const fwd_slash = "\\" | ||
const empty_stringCode = " ".charCodeAt(0) | ||
/** | ||
@@ -62,2 +18,3 @@ * JSON Encoder/Decoder for AssemblyScript | ||
export namespace JSON { | ||
export type _Variant = Variant; | ||
/** | ||
@@ -68,33 +25,47 @@ * Stringifies valid JSON data. | ||
* ``` | ||
* @param data unknown | ||
* @param data T | ||
* @returns string | ||
*/ | ||
*/ | ||
export function stringify<T = Nullable | null>(data: T): string { | ||
// String | ||
if (isString(data)) { | ||
return serializeString(<string>data); | ||
} | ||
// Boolean | ||
else if (isBoolean(data)) { | ||
return data ? "true" : "false"; | ||
} | ||
// Null | ||
else if (isNullable<T>() && data == null) { | ||
return "null"; | ||
} | ||
// Integers/Floats | ||
// @ts-ignore | ||
if (isString(data)) { | ||
return serializeString(<string>data) | ||
} else if (isBoolean(data)) { | ||
return serializeBoolean(data) | ||
else if ((isInteger<T>() || isFloat<T>()) && isFinite(data)) { | ||
// @ts-ignore | ||
} else if (isNullable(data) && data == null) { | ||
return nullVal | ||
} else if (isFloat(data) || isInteger(data)) { | ||
return data.toString() | ||
} else if (isArrayLike(data)) { | ||
// @ts-ignore | ||
return serializeArray<T>(data) | ||
} else if (data instanceof unknown) { | ||
return serializeUnknown(data) | ||
} else if (data instanceof DynamicObject) { | ||
return serializeDynamicObject(data) | ||
return data.toString(); | ||
} | ||
// Class-Based serialization | ||
// @ts-ignore | ||
if (data.__encoded.length === 0) data.__encode() | ||
// @ts-ignore | ||
return lcbracket + data.__encoded + rcbracket | ||
else if (isDefined(data.__JSON_Serialize)) { | ||
//@ts-ignore | ||
return data.__JSON_Serialize(); | ||
} | ||
// ArrayLike | ||
else if (isArrayLike(data)) { | ||
let result = new StringSink("["); | ||
if (data.length == 0) return "[]"; | ||
for (let i = 0; i < data.length - 1; i++) { | ||
result.write(stringify(unchecked(data[i]))); | ||
result.write(","); | ||
} | ||
result.write(stringify(unchecked(data[data.length - 1]))); | ||
result.write("]"); | ||
return result.toString(); | ||
} else { | ||
return "null"; | ||
} | ||
} | ||
/** | ||
* Parses valid JSON strings into their original format. | ||
* Useful for exchanging data and cloning. | ||
* ```js | ||
@@ -106,676 +77,264 @@ * JSON.parse<T>(data) | ||
*/ | ||
export function parse<T = Nullable | null>(data: string): T { | ||
const char = data.charCodeAt(0) | ||
let type!: T | ||
// @ts-ignore | ||
if (isString<T>()) return parseString(data.trim()) | ||
// @ts-ignore | ||
else if (isBoolean<T>()) return parseBoolean(data.trimLeft()) | ||
// @ts-ignore | ||
else if (isArrayLike<T>()) return parseArray<T>(data) | ||
// @ts-ignore | ||
else if (isNullable<T>() && char === nCode) return null | ||
// @ts-ignore | ||
else if (isFloat<T>() || isInteger<T>()) return parseNumber<T>(data.trim()) | ||
// @ts-ignore | ||
else if (type instanceof unknown) return parseUnknown(data) | ||
// @ts-ignore | ||
else if (type instanceof DynamicObject) return parseDynamicObject(data) | ||
// @ts-ignore | ||
return parseObject<T>(data) | ||
} | ||
} | ||
export function parse<T = Variant>(data: string): T { | ||
let type!: T; | ||
if (isString<T>()) { | ||
// @ts-ignore | ||
return parseString(data); | ||
} else if (isBoolean<T>()) { | ||
// @ts-ignore | ||
return parseBoolean<T>(data); | ||
} else if (isFloat<T>() || isInteger<T>()) { | ||
return parseNumber<T>(data); | ||
} else if (isArrayLike<T>()) { | ||
return parseArray<T>(data); | ||
// @ts-ignore | ||
} else if (isDefined(type.__JSON_Deserialize)) { | ||
const len: u32 = data.length - 1 | ||
let schema!: T | ||
const result = new Map<string, string>() | ||
let lastPos: u32 = 1 | ||
let key: string = '' | ||
let instr: u32 = 0 | ||
let char: u32 = 0 | ||
let depth: u32 = 0 | ||
let fdepth: u32 = 0 | ||
for (let i: u32 = 1; i < len; i++) { | ||
char = data.charCodeAt(i) | ||
if (char === "\"".charCodeAt(0) && data.charCodeAt(i - 1) !== "/".charCodeAt(0)) instr = (instr ? 0 : 1) | ||
else if (instr === 0) { | ||
if (char === leftBraceCode || char === leftBracketCode) depth++ | ||
if (char === rightBraceCode || char === rightBracketCode) fdepth++ | ||
} | ||
if (depth !== 0 && depth === fdepth) { | ||
result.set(key, data.slice(lastPos + 1, i + 1)) | ||
// Reset the depth | ||
depth = 0 | ||
fdepth = 0 | ||
// Set new lastPos | ||
lastPos = i + 1 | ||
} | ||
if (depth === 0) { | ||
if (char === colonCode) { | ||
key = data.slice(lastPos + 1, i - 1) | ||
lastPos = i | ||
} | ||
else if (char === commaCode) { | ||
if ((i - lastPos) > 0) result.set(key, data.slice(lastPos + 1, i)) | ||
lastPos = i + 1 | ||
} | ||
} | ||
} | ||
export function serializeDynamicObject(data: DynamicObject): string { | ||
const result = new StringSink(lcbracket) | ||
const keys = DynamicObject.keys(data) | ||
const values = DynamicObject.values(data) | ||
const len: u32 = keys.length - 1 | ||
if (len === -1) return '{}' | ||
for (let i: u32 = 0; i < len; i++) { | ||
result.write(`"${unchecked(keys[i])}":${serializeUnknown(unchecked(values[i]))},`) | ||
} | ||
result.write(`"${unchecked(keys[len])}":${serializeUnknown(unchecked(values[len]))}}`) | ||
return result.toString() | ||
} | ||
export function serializeUnknown(data: unknown): string { | ||
// @ts-ignore | ||
if (data.type === unknownTypes.null) { | ||
return nullVal | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownId) { | ||
// @ts-ignore | ||
return serializeUnknown(data.get<unknown>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === stringId) { | ||
// @ts-ignore | ||
return serializeString(data.get<string>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.boolean) { | ||
// @ts-ignore | ||
return serializeBoolean(data.get<boolean>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.i8) { | ||
// @ts-ignore | ||
return data.get<i8>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.i16) { | ||
// @ts-ignore | ||
return data.get<i16>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.i32) { | ||
// @ts-ignore | ||
return data.get<i32>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.i64) { | ||
// @ts-ignore | ||
return data.get<i64>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.u8) { | ||
// @ts-ignore | ||
return data.get<u8>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.u16) { | ||
// @ts-ignore | ||
return data.get<u16>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.u32) { | ||
// @ts-ignore | ||
return data.get<u32>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.u64) { | ||
// @ts-ignore | ||
return data.get<u64>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.f32) { | ||
// @ts-ignore | ||
return data.get<f32>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === unknownTypes.f64) { | ||
// @ts-ignore | ||
return data.get<f64>().toString() | ||
} | ||
// @ts-ignore | ||
else if (data.type === objectId) { | ||
// @ts-ignore | ||
return serializeDynamicObject(data.get<DynamicObject>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayUnknownId) { | ||
// @ts-ignore | ||
return serializeUnknownArray(data.get<unknown[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayBoolId) { | ||
// @ts-ignore | ||
return serializeBooleanArray(data.get<bool[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayBooleanId) { | ||
// @ts-ignore | ||
return serializeBooleanArray(data.get<boolean[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayF32Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<f32[]>(data.get<f32[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayF64Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<f64[]>(data.get<f64[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayU8Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<u8[]>(data.get<u8[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayU16Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<u16[]>(data.get<u16[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayU32Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<u32[]>(data.get<u32[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayU64Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<u64[]>(data.get<u64[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayI8Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<i8[]>(data.get<i8[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayI16Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<i16[]>(data.get<i16[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayI32Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<i32[]>(data.get<i32[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayI64Id) { | ||
// @ts-ignore | ||
return serializeNumberArray<i64[]>(data.get<i64[]>()) | ||
} | ||
// @ts-ignore | ||
else if (data.type === arrayStringId) { | ||
// @ts-ignore | ||
return serializeStringArray(data.get<string[]>()) | ||
} | ||
// @ts-ignore | ||
else { | ||
return nullVal | ||
} | ||
} | ||
export function serializeNumber<T>(data: T): string { | ||
// @ts-ignore | ||
return data.toString() | ||
} | ||
export function serializeString(data: string): string { | ||
return quote + data.replaceAll(quote, escapeQuote) + quote | ||
} | ||
export function serializeBoolean(data: number): string { | ||
return data ? trueVal : falseVal | ||
} | ||
function serializeStringArray(data: string[]): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
for (let i: u32 = 0; i < len; i++) { | ||
result.write(serializeString(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeString(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
function serializeNumberArray<T extends Array<any>>(data: T): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
for (let i: u32 = 0; i < len; i++) { | ||
result.write(serializeNumber<valueof<T>>(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeNumber<valueof<T>>(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
function serializeBooleanArray(data: boolean[]): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
for (let i: u32 = 0; i < len; i++) { | ||
// @ts-ignore | ||
result.write(serializeBoolean(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
// @ts-ignore | ||
result.write(serializeBoolean(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
function serializeUnknownArray(data: unknown[]): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
for (let i: u32 = 0; i < len; i++) { | ||
result.write(serializeUnknown(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeUnknown(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
function serializeDeepArray<T extends Array<any>>(data: T): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
for (let i: u32 = 0; i < len; i++) { | ||
result.write(serializeArray<valueof<T>>(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeArray<valueof<T>>(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
function serializeObjectArray<T extends Array<any>>(data: T): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
let obj!: valueof<T> | ||
for (let i: u32 = 0; i < len; i++) { | ||
obj = unchecked(data[i]) | ||
if (obj.__encoded.length === 0) obj.__encode() | ||
result.write(obj.__encoded) | ||
result.writeCodePoint(commaCode) | ||
} | ||
obj = unchecked(data[len]) | ||
if (obj.__encoded.length === 0) obj.__encode() | ||
result.write(obj.__encoded) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
function serializeDynamicObjectArray(data: DynamicObject[]): string { | ||
const result = new StringSink(lbracket) | ||
const len: u32 = data.length - 1 | ||
for (let i: u32 = 0; i < len; i++) { | ||
result.write(serializeDynamicObject(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeDynamicObject(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} | ||
export function serializeArray<T extends Array<any>>(data: T): string { | ||
let type!: valueof<T> | ||
const len = data.length - 1; | ||
if (len === -1) return lbracket + rbracket | ||
let result = new StringSink(lbracket); | ||
if (isString<valueof<T>>()) { | ||
for (let i = 0; i < len; i++) { | ||
result.write(serializeString(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeString(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) { | ||
for (let i = 0; i < len; i++) { | ||
result.write(serializeNumber<valueof<T>>(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeNumber<valueof<T>>(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} else if (isBoolean<valueof<T>>()) { | ||
for (let i = 0; i < len; i++) { | ||
result.write(serializeBoolean(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeBoolean(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
// @ts-ignore | ||
} else if (type instanceof unknown) { | ||
for (let i = 0; i < len; i++) { | ||
result.write(serializeUnknown(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeUnknown(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} else if (isArray<valueof<T>>()) { | ||
for (let i = 0; i < len; i++) { | ||
result.write(serializeArray<valueof<T>>(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeArray<valueof<T>>(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
// @ts-ignore | ||
} else if (type instanceof DynamicObject) { | ||
for (let i = 0; i < len; i++) { | ||
result.write(serializeDynamicObject(unchecked(data[i]))) | ||
result.writeCodePoint(commaCode) | ||
} | ||
result.write(serializeDynamicObject(unchecked(data[len]))) | ||
result.writeCodePoint(rbracketCode) | ||
return result.toString() | ||
} else { | ||
for (let i = 0; i < len; i++) { | ||
const elem = unchecked(data[i]) | ||
if ((len - lastPos) > 0) result.set(key, data.slice(lastPos + 1, len)) | ||
// @ts-ignore | ||
if (elem.__encoded.length === 0) elem.__encode() | ||
return schema.__JSON_Deserialize(result) | ||
} else { | ||
// @ts-ignore | ||
return null; | ||
} | ||
// @ts-ignore | ||
result.write(elem.__encoded) | ||
result.writeCodePoint(rcbracketCode) | ||
} | ||
return result.toString() | ||
} | ||
export function parseUnknown(data: string): unknown { | ||
const char = data.charCodeAt(0) | ||
// @ts-ignore | ||
if (char === quoteCode) return unknown.wrap(parseString(data)) | ||
// @ts-ignore | ||
else if (char === t_charCode) return unknownTrue | ||
else if (char === f_charCode) return unknownFalse | ||
// @ts-ignore | ||
else if (char === lbracketCode) return unknown.wrap(parseUnknownArray(data)) | ||
// @ts-ignore | ||
else if (char === nCode) return unknownNull | ||
// @ts-ignore | ||
//else if (char === lcbracketCode) return parseObject<T>(data) | ||
// @ts-ignore | ||
return parseUnknownNumber(data) | ||
// @ts-ignore | ||
@inline | ||
function serializeString(data: string): string { | ||
return '"' + data.replaceAll('"', '\\"') + '"'; | ||
} | ||
export function parseBoolean(data: string): boolean { | ||
return data.charCodeAt(0) === t_charCode ? true : false | ||
// @ts-ignore | ||
@inline | ||
function parseString(data: string): string { | ||
return data.slice(1, data.length - 1).replaceAll('\\"', '"'); | ||
} | ||
export function parseString(data: string): string { | ||
return data.slice(1, data.length - 1).replaceAll(escapeQuote, quote) | ||
// @ts-ignore | ||
@inline | ||
function parseBoolean<T extends boolean>(data: string): T { | ||
if (data.length > 3 && data.startsWith("true")) return <T>true; | ||
else if (data.length > 4 && data.startsWith("false")) return <T>false; | ||
else throw new Error(`JSON: Cannot parse "${data}" as boolean`); | ||
} | ||
export function parseNumber<T>(data: string): T { | ||
let type: T | ||
// @ts-ignore | ||
@inline | ||
function parseNumber<T>(data: string): T { | ||
let type: T; | ||
// @ts-ignore | ||
if (type instanceof f64) return F64.parseFloat(data) | ||
if (type instanceof f64) return F64.parseFloat(data); | ||
// @ts-ignore | ||
else if (type instanceof f32) return F32.parseFloat(data) | ||
else if (type instanceof f32) return F32.parseFloat(data); | ||
// @ts-ignore | ||
else if (type instanceof i32) return I32.parseInt(data) | ||
else if (type instanceof i32) return I32.parseInt(data); | ||
// @ts-ignore | ||
else if (type instanceof u32) return U32.parseInt(data) | ||
else if (type instanceof u32) return U32.parseInt(data); | ||
// @ts-ignore | ||
else if (type instanceof u64) return U64.parseInt(data) | ||
else if (type instanceof u8) return U8.parseInt(data); | ||
// @ts-ignore | ||
else if (type instanceof i64) return I64.parseInt(data) | ||
else if (type instanceof u16) return U16.parseInt(data); | ||
// @ts-ignore | ||
else if (type instanceof u8) return U8.parseInt(data) | ||
else if (type instanceof i16) return I16.parseInt(data); | ||
// @ts-ignore | ||
else if (type instanceof u16) return U16.parseInt(data) | ||
// @ts-ignore | ||
else if (type instanceof i16) return I16.parseInt(data) | ||
// @ts-ignore | ||
return I8.parseInt(data) | ||
else if (type instanceof i8) return I8.parseInt(data); | ||
else | ||
throw new Error( | ||
`JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.` | ||
); | ||
} | ||
export function parseUnknownNumber(data: string): unknown { | ||
// @ts-ignore | ||
if (data.includes('.')) return unknown.wrap(F64.parseFloat(data)) | ||
// @ts-ignore | ||
return unknown.wrap(I64.parseInt(data)) | ||
} | ||
export function parseArray<T extends Array<unknown>>(data: string): T { | ||
let type!: valueof<T> | ||
// @ts-ignore | ||
if (isString<valueof<T>>()) return parseStringArray(data) | ||
// @ts-ignore | ||
else if (isBoolean<valueof<T>>()) return parseBooleanArray(data) | ||
// @ts-ignore | ||
else if (isArray<valueof<T>>()) return parseArrayArray<T>(data) | ||
// @ts-ignore | ||
else if (type instanceof unknown) return parseUnknownArray(data) | ||
// @ts-ignore | ||
return parseNumberArray<valueof<T>>(data) | ||
} | ||
export function parseStringArray(data: string): Array<string> { | ||
const result = new Array<string>() | ||
if (data.length === 2) return result | ||
let lastPos: u32 = 1 | ||
let char: u32 = 0 | ||
let instr: boolean = false | ||
for (let i: u32 = 1; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i) | ||
// This ignores [ and ] or { and } if they are inside a string. | ||
if (char === quoteCode && data.charCodeAt(i - 1) !== fwd_slashCode) instr = instr ? false : true | ||
if (instr === false) { | ||
// Handles whitespace after a comma | ||
if (char === WS1code || char === WS2code || char === WS3code || char === WS4code || char === WS5code) lastPos++ | ||
if (char === quoteCode) { | ||
result.push(parseString(data.slice(lastPos, i + 1))) | ||
lastPos = i + 2 | ||
} | ||
// @ts-ignore | ||
@inline | ||
export function parseNumberArray<T>(data: string): T { | ||
const result = instantiate<T>(); | ||
if (data.length == 0) return result; | ||
let lastPos: u32 = 1; | ||
let i: u32 = 1; | ||
let char: u32 = 0; | ||
for (; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i); | ||
if (char == commaCode) { | ||
// console.log(data.slice(lastPos, i)) | ||
// @ts-ignore | ||
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i).trim())); | ||
lastPos = ++i; | ||
} | ||
} | ||
return result | ||
//console.log(data.slice(lastPos, data.length - 1)) | ||
// @ts-ignore | ||
result.push( | ||
// @ts-ignore | ||
parseNumber<valueof<T>>(data.slice(lastPos, data.length - 1).trimStart()) | ||
); | ||
return result; | ||
} | ||
export function parseBooleanArray(data: string): Array<boolean> { | ||
const result = new Array<boolean>() | ||
if (data.length === 2) return result | ||
let char: u32 = 0 | ||
let instr: boolean = false | ||
for (let i: u32 = 1; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i) | ||
if (instr === false) { | ||
if (char === t_charCode) { | ||
result.push(true) | ||
i += 4 | ||
} else { | ||
result.push(false) | ||
i += 5 | ||
} | ||
} | ||
} | ||
return result | ||
} | ||
export function parseNumberArray<T>(data: string): Array<T> { | ||
const result = new Array<T>() | ||
if (data.length === 2) return result | ||
let lastPos: u32 = 0 | ||
let char: u32 = 0 | ||
let i: u32 = 1 | ||
// @ts-ignore | ||
@inline | ||
export function parseBooleanArray<T>(data: string): T { | ||
const result = instantiate<T>(); | ||
if (data.length == 0) return result; | ||
let lastPos: u32 = 1; | ||
let i: u32 = 1; | ||
let char: u32 = 0; | ||
for (; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i) | ||
if (char === commaCode) { | ||
//console.log('Found number: ' + data.slice(lastPos + 1, i)) | ||
result.push(parseNumber<T>(data.slice(lastPos + 1, i))) | ||
lastPos = i | ||
char = data.charCodeAt(i); | ||
if (char == commaCode) { | ||
// @ts-ignore | ||
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i).trimStart())); | ||
lastPos = ++i; | ||
} | ||
} | ||
// console.log('Found number: ' + data.slice(lastPos + 1, i)) | ||
result.push(parseNumber<T>(data.slice(lastPos + 1, i))) | ||
return result | ||
// @ts-ignore | ||
result.push( | ||
// @ts-ignore | ||
parseBoolean<valueof<T>>(data.slice(lastPos, data.length - 1).trimStart()) | ||
); | ||
return result; | ||
} | ||
export function parseUnknownArray(data: string): Array<unknown> { | ||
const result = new Array<unknown>() | ||
if (data.length === 2) return result | ||
let lastPos: i32 = 0 | ||
let char: u32 = 0 | ||
let depth: u32 = 0 | ||
let fdepth: u32 = 0 | ||
let instr: boolean = false | ||
let i: u32 = 1 | ||
for (; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i) | ||
// This ignores [ and ] if they are inside a string. | ||
if (char === quoteCode && data.charCodeAt(i - 1) !== fwd_slashCode) { | ||
if (instr === true) { | ||
instr = false | ||
} else { | ||
instr = true | ||
} | ||
// @ts-ignore | ||
@inline | ||
export function parseArray<T>(data: string): T { | ||
const result = instantiate<T>(); | ||
data = data.trim(); | ||
let len: u32 = data.length - 1; | ||
let lastPos: u32 = 1; | ||
let i: u32 = 1; | ||
let char: u32 = 0; | ||
// Is struct such as Object, or Array | ||
let isStruct: boolean = false; | ||
let isStr: boolean = false; | ||
//let offset: u32 = 0; | ||
// Depth for finding matching brackets | ||
let inDepth: u32 = 0; | ||
let outDepth: u32 = 0; | ||
for (; i < len; i++) { | ||
char = data.charCodeAt(i); | ||
if (char == quoteCode && data.charCodeAt(i - 1) != backSlashCode) | ||
isStr = !isStr; | ||
if (char == leftBraceCode || char == leftBracketCode) { | ||
inDepth++; | ||
isStruct = true; | ||
} else if (char == rightBraceCode || char == rightBracketCode) { | ||
outDepth++; | ||
isStruct = true; | ||
} | ||
if (instr === false) { | ||
if (char === commaCode && depth === 0 && fdepth === 0) { | ||
//console.log('Normal chunk: ' + data.slice(lastPos + 1, i)) | ||
result.push(parseUnknown(data.slice(lastPos + 1, i).trim())) | ||
lastPos = i | ||
} else if (char === lbracketCode) depth++ | ||
else if (char === rbracketCode) fdepth++ | ||
else if (depth !== 0 && depth === fdepth) { | ||
//console.log('Deep chunk: ' + data.slice(lastPos + 1, i)) | ||
result.push(unknown.wrap(parseUnknownArray(data.slice(lastPos + 1, i).trim()))) | ||
// Reset the depth | ||
depth = 0 | ||
fdepth = 0 | ||
// Set new lastPos | ||
lastPos = i | ||
} | ||
} | ||
} | ||
// console.log('Last chunk: ' + data.slice(lastPos + 1, data.length - 1).trim()) | ||
result.push(parseUnknown(data.slice(lastPos + 1, data.length - 1).trim())) | ||
return result | ||
} | ||
export function parseArrayArray<T extends Array<unknown>>(data: string): T { | ||
const result = instantiate<T>() | ||
if (data.length === 2) return result | ||
let lastPos: i32 = -1 | ||
let char: u32 = 0 | ||
let depth: u32 = 0 | ||
let fdepth: u32 = 0 | ||
let instr: u32 = 0 | ||
for (let i: u32 = 1; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i) | ||
// This ignores [ and ] if they are inside a string. | ||
if (char === quoteCode && data.charCodeAt(i - 1) !== fwd_slashCode) instr = instr ? 0 : 1 | ||
// This gets the depth of the array. | ||
if (instr === 0) { | ||
if (char === lbracketCode) depth++ | ||
if (char === rbracketCode) fdepth++ | ||
// If the depth and found depth are equal, that is an array. Push it. | ||
if (depth !== 0 && depth === fdepth) { | ||
result.push( | ||
if (!isStr) { | ||
if (!isStruct) { | ||
// This removes whitespace before and after an element | ||
/*if (offset != 0 && isSpace(char)) { | ||
lastPos++; | ||
} else { | ||
if (isSpace(char)) offset++; | ||
}*/ | ||
// This checks to see if we are dealing with structures such as Objects and Arrays | ||
if (char == commaCode) { | ||
// @ts-ignore | ||
parseArray<valueof<T>>(data.slice(lastPos + 2, i + 1)) | ||
) | ||
// Reset the depth | ||
depth = 0 | ||
fdepth = 0 | ||
// Set new lastPos | ||
lastPos = i | ||
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i).trim())); | ||
//offset = 0; | ||
lastPos = i + 1; | ||
} | ||
} else { | ||
if (inDepth == outDepth) { | ||
i++; | ||
//console.log(`Struct-${data.slice(lastPos, i).trim()}-`) | ||
lastPos = i + 1; | ||
inDepth = 0; | ||
outDepth = 0; | ||
isStruct = false; | ||
} | ||
} | ||
} | ||
} | ||
// Return the final array | ||
return result | ||
} | ||
export function parseObject<T>(data: string): T { | ||
//console.log('Data ' + data) | ||
data = removeJSONWhitespace(data) | ||
const len: u32 = data.length - 1 | ||
let schema: T | ||
const result = new Map<string, string>() | ||
let lastPos: u32 = 1 | ||
let key: string = '' | ||
let instr: u32 = 0 | ||
let char: u32 = 0 | ||
let depth: u32 = 0 | ||
let fdepth: u32 = 0 | ||
for (let i: u32 = 1; i < len; i++) { | ||
char = data.charCodeAt(i) | ||
if (char === quoteCode && data.charCodeAt(i - 1) !== fwd_slashCode) instr = (instr ? 0 : 1) | ||
else if (instr === 0) { | ||
if (char === lcbracketCode || char === lbracketCode) depth++ | ||
if (char === rcbracketCode || char === rbracketCode) fdepth++ | ||
} | ||
if (depth !== 0 && depth === fdepth) { | ||
//console.log(`Deep: ${data.slice(lastPos + 1, i + 1)}`) | ||
result.set(key, data.slice(lastPos + 1, i + 1).trim()) | ||
// Reset the depth | ||
depth = 0 | ||
fdepth = 0 | ||
// Set new lastPos | ||
lastPos = i + 1 | ||
} | ||
if (depth === 0) { | ||
if (char === colonCode) { | ||
//console.log(`Key: ${data.slice(lastPos + 1, i - 1)}`) | ||
key = data.slice(lastPos + 1, i - 1).trim() | ||
lastPos = i | ||
} | ||
else if (char === commaCode) { | ||
//console.log(`Value: ${data.slice(lastPos + 1, i)}`) | ||
if ((i - lastPos) > 0) result.set(key, data.slice(lastPos + 1, i).trim()) | ||
lastPos = i + 1 | ||
} | ||
} | ||
/*char = data.charCodeAt(lastPos) | ||
// Remove preceeding whitespace | ||
while (isSpace(char)) { | ||
lastPos++; | ||
char = data.charCodeAt(lastPos); | ||
} | ||
//console.log(`Trailing: ${data.slice(lastPos + 1, len)}\n\t\sValid: ${data.slice(lastPos + 1, len).length > 0}`) | ||
char = data.charCodeAt(--len); | ||
while (isSpace(char)) { | ||
len--; | ||
char = data.charCodeAt(len); | ||
}*/ | ||
if ((len - lastPos) > 0) result.set(key, data.slice(lastPos + 1, len).trim()) | ||
// @ts-ignore | ||
return schema.__decode(result) | ||
// Handle empty arrays | ||
data = data.slice(lastPos, len).trim(); | ||
// @ts-ignore | ||
if (data.length != 0) result.push(JSON.parse<valueof<T>>(data)); | ||
//if (data.length != 0) console.log(`Trailing-${data.slice(lastPos, len).trim()}-`) | ||
return result; | ||
} | ||
export function parseDynamicObject(data: string): DynamicObject { | ||
const len: u32 = data.length - 1 | ||
if (len === 1) return new DynamicObject() | ||
const result = new Map<string, unknown>() | ||
let lastPos: u32 = 1 | ||
let key: string = '' | ||
let instr: u32 = 0 | ||
let char: u32 = 0 | ||
let depth: u32 = 0 | ||
let fdepth: u32 = 0 | ||
for (let i: u32 = 1; i < len; i++) { | ||
char = data.charCodeAt(i) | ||
if (char === quoteCode && data.charCodeAt(i - 1) !== fwd_slashCode) instr = (instr ? 0 : 1) | ||
else if (instr === 0) { | ||
if (char === lcbracketCode || char === lbracketCode) depth++ | ||
if (char === rcbracketCode || char === rbracketCode) fdepth++ | ||
} | ||
if (depth !== 0 && depth === fdepth) { | ||
result.set(key, unknown.wrap(data.slice(lastPos + 1, i + 1).trim())) | ||
// Reset the depth | ||
depth = 0 | ||
fdepth = 0 | ||
// Set new lastPos | ||
lastPos = i + 2 | ||
} | ||
if (depth === 0) { | ||
if (char === colonCode) { | ||
key = data.slice(lastPos + 1, i - 1).trim() | ||
lastPos = i + 1 | ||
export function parseObject(data: string): void { | ||
//const obj = instantiate<T>() | ||
const result = new Array<string>(); | ||
let lastPos: u32 = 0; | ||
let char: u32 = 0; | ||
let i: u32 = 1; | ||
let key: string = ""; | ||
let isKey: boolean = false; | ||
for (; i < u32(data.length - 1); i++) { | ||
char = data.charCodeAt(i); | ||
if (isKey == false) { | ||
if (char == colonCode) { | ||
key = data.slice(lastPos + 2, i - 1); | ||
//console.log(`Found Key: ${key}`); | ||
result.push(key); | ||
lastPos = ++i; | ||
isKey = true; | ||
} | ||
else if (char === commaCode) { | ||
if ((i - lastPos) > 0) result.set(key, unknown.wrap(data.slice(lastPos + 1, i).trim())) | ||
lastPos = i + 1 | ||
} else { | ||
if (char == commaCode) { | ||
const val = data.slice(lastPos, i); | ||
lastPos = i; | ||
isKey = false; | ||
//console.log(`Found Val: ${val}`) | ||
result.push(val); | ||
} | ||
} | ||
} | ||
if ((len - lastPos) > 0) result.set(key, unknown.wrap(data.slice(lastPos + 1, len - 1).trim())) | ||
const o = new DynamicObject() | ||
// @ts-ignore | ||
o.__data = result | ||
return o | ||
result.push(data.slice(lastPos, data.length - 1)); | ||
//console.log(stringify(result)) | ||
//return obj | ||
} | ||
export function removeJSONWhitespace(data: string): string { | ||
let result = new StringSink() | ||
let instr = false | ||
let char = 0 | ||
for (let i = 0; i < data.length; i++) { | ||
char = data.charCodeAt(i) | ||
if (char === quoteCode && data.charCodeAt(i - 1) === fwd_slashCode) { | ||
instr = !instr | ||
} | ||
if (instr === true) { | ||
result.writeCodePoint(char) | ||
} else if (instr === false && char !== empty_stringCode) { | ||
result.writeCodePoint(char) | ||
} | ||
} | ||
return result.toString() | ||
} | ||
class Nullable { } |
@@ -1,207 +0,35 @@ | ||
import { unknown, unknownTypes } from './unknown' | ||
import "wasi"; | ||
import { JSON } from "."; | ||
import { console, stringify } from "../node_modules/as-console/assembly/wasi" | ||
import { JSON, parseDynamicObject, parseUnknown, parseUnknownArray, removeJSONWhitespace } from '.' | ||
import { DynamicObject } from './DynamicObject' | ||
/* | ||
// Not inlining results in an error for some reason | ||
// @ts-ignore | ||
@inline | ||
function check<T>(message: string, data: T): void { | ||
const encoded = JSON.stringify<T>(data) | ||
const decoded = JSON.parse<T>(encoded) | ||
if (encoded == JSON.stringify(decoded)) { | ||
console.log(`Success: ${message}`) | ||
} else { | ||
console.log(`Fail: ${message}`) | ||
} | ||
} | ||
// @ts-ignore | ||
@json | ||
class EmptySchema { } | ||
// @ts-ignore | ||
@json | ||
class JSONSchema { | ||
string1: string | ||
string2: string | ||
string3: string | ||
f641: f64 | ||
f642: f64 | ||
f643: f64 | ||
f644: f64 | ||
f645: f64 | ||
f646: f64 | ||
f321: f32 | ||
f322: f32 | ||
f323: f32 | ||
f324: f32 | ||
f325: f32 | ||
f326: f32 | ||
u8: u8 | ||
u16: u16 | ||
u32: u32 | ||
u64: u64 | ||
i8: i8 | ||
i16: i16 | ||
i32: i32 | ||
i64: i64 | ||
bool: bool | ||
boolean: boolean | ||
stringArr: string[] | ||
f64Arr: f64[] | ||
u8Arr: u8[] | ||
u16Arr: u16[] | ||
u32Arr: u32[] | ||
u64Arr: u64[] | ||
i8Arr: i8[] | ||
i16Arr: i16[] | ||
i32Arr: i32[] | ||
i64Arr: i64[] | ||
emptyArr: string[] | ||
boolArr: bool[] | ||
booleanArr: boolean[] | ||
stringArrArr: string[][] | ||
object: JSONSchema2 | ||
class Vec2 { | ||
x: f32 | ||
y: f32 | ||
} | ||
// @ts-ignore | ||
@json | ||
class JSONSchema2 { | ||
string1: string | ||
class Player { | ||
firstName: string | ||
lastName: string | ||
lastActive: i32[] | ||
age: i32 | ||
pos: Vec2 | ||
} | ||
const obj: JSONSchema = { | ||
string1: 'Hello World', | ||
string2: 'Hell[}o Wo[rld}{', | ||
string3: 'Hel`"lo Wo"`r"ld', | ||
f641: 7.23, | ||
f642: 10e2, | ||
f643: 10E2, | ||
f644: 123456e-5, | ||
f645: 123456E-5, | ||
f646: 0.0, | ||
f321: 7.23, | ||
f322: 10e2, | ||
f323: 10E2, | ||
f324: 123456e-5, | ||
f325: 123456E-5, | ||
f326: 0.0, | ||
u8: 100, | ||
u16: 101, | ||
u32: 102, | ||
u64: 103, | ||
i8: -100, | ||
i16: -101, | ||
i32: -102, | ||
i64: -103, | ||
bool: true, | ||
boolean: false, | ||
stringArr: ['Hello World', 'Hell[}o Wo[rld}{', 'Hel`"lo Wo"`r"ld'], | ||
f64Arr: [7.23, 10e2, 10e2, 10E2, 123456e-5, 123456E-5, 0.0], | ||
u8Arr: [100, 100, 100], | ||
u16Arr: [101, 101, 101], | ||
u32Arr: [102, 102, 102], | ||
u64Arr: [103, 103, 103], | ||
i8Arr: [-100, -100, -100], | ||
i16Arr: [-101, -101, -101], | ||
i32Arr: [-102, -102, -102], | ||
i64Arr: [-103, -103, -103], | ||
emptyArr: [], | ||
boolArr: [true, false, true], | ||
booleanArr: [true, false, true], | ||
stringArrArr: [['Hey'], ['ha'], ['ho']], | ||
object: { | ||
string1: 'Hello World' | ||
} | ||
const data: Player = { | ||
firstName: "Emmet", | ||
lastName: "West", | ||
lastActive: [8, 27, 2022], | ||
age: 23, | ||
pos: { | ||
x: -3.4, | ||
y: 1.2 | ||
} | ||
} | ||
const emptyObj: EmptySchema = {} | ||
// Strings | ||
check<string>('Encode/Decode String', 'Hello World') | ||
check<string>('Encode/Decode String', 'Hell[}o Wo[rld}{') | ||
check<string>('Encode/Decode String', 'Hel`"lo Wo"`r"ld') | ||
// Floats | ||
check<f64>('Encode/Decode f64', 7.23) | ||
check<f64>('Encode/Decode f64', 10e2) | ||
check<f64>('Encode/Decode f64', 10E2) | ||
check<f64>('Encode/Decode f64', 123456e-5) | ||
check<f64>('Encode/Decode f64', 123456E-5) | ||
check<f64>('Encode/Decode f64', 0.0) | ||
const stringified = JSON.stringify<Player>(data); | ||
// '{"firstName":"Emmet","lastName":"West","lastActive":[8,27,2022],"age":23}' | ||
console.log(`Stringified: ${stringified}`); | ||
check<f32>('Encode/Decode f32', 7.23) | ||
check<f32>('Encode/Decode f32', 10e2) | ||
check<f32>('Encode/Decode f32', 10E2) | ||
check<f32>('Encode/Decode f32', 123456e-5) | ||
check<f32>('Encode/Decode f32', 123456E-5) | ||
check<f32>('Encode/Decode f32', 0.0) | ||
// Integers | ||
check<u8>('Encode/Decode u8', 100) | ||
check<u16>('Encode/Decode u16', 101) | ||
check<u32>('Encode/Decode u32', 102) | ||
check<u64>('Encode/Decode u64', 103) | ||
check<i8>('Encode/Decode i8', -100) | ||
check<i16>('Encode/Decode i16', -101) | ||
check<i32>('Encode/Decode i32', -102) | ||
check<i64>('Encode/Decode i64', -103) | ||
// Bools | ||
check<bool>('Encode/Decode bool', true) | ||
check<bool>('Encode/Decode bool', false) | ||
// Booleans | ||
check<boolean>('Encode/Decode boolean', true) | ||
check<boolean>('Encode/Decode boolean', false) | ||
// Null | ||
check('Encode/Decode null', null) | ||
// Arrays | ||
check<string[]>('Encode/Decode string[]', ['Hello World', 'Hell[}o Wo[rld}{', 'Hel`"lo Wo"`r"ld']) | ||
check<f64[]>('Encode/Decode f32[]', [7.23, 10e2, 10e2, 10E2, 123456e-5, 123456E-5, 0.0]) | ||
check<u8[]>('Encode/Decode u8[]', [100, 100, 100]) | ||
check<u16[]>('Encode/Decode u16[]', [101, 101, 101]) | ||
check<u32[]>('Encode/Decode u32[]', [102, 102, 102]) | ||
check<u64[]>('Encode/Decode u64[]', [103, 103, 103]) | ||
check<i8[]>('Encode/Decode i8[]', [-100, -100, -100]) | ||
check<i16[]>('Encode/Decode i16[]', [-101, -101, -101]) | ||
check<i32[]>('Encode/Decode i32[]', [-102, -102, -102]) | ||
check<i64[]>('Encode/Decode i64[]', [-103, -103, -103]) | ||
check<string[]>('Encode/Decode empty[]', []) | ||
check<bool[]>('Encode/Decode bool[]', [true, false, true]) | ||
check<boolean[]>('Encode/Decode boolean[]', [true, false, true]) | ||
check<string[][]>('Encode/Decode string[][]', [['Hey'], ['ha'], ['ho']]) | ||
// Object | ||
check<JSONSchema>('Encode/Decode object', obj) | ||
check<EmptySchema>('Encode/Decode object', emptyObj) | ||
*/ | ||
// Unknown | ||
//check<unknown[]>('Encode/Decode unknown[]', ["Welcome to dynamic arrays", ["Very", ["Deep", ["Array"]]], "It also supports nulls"]) | ||
//console.log(JSON.stringify(["Welcome to dynamic arrays", 3.14, ["Very", ["Deep", ["Array"]]], true, "It also supports nulls", null])) | ||
//console.log(JSON.stringify(JSON.parse<unknown[]>('["Welcome to dynamic arrays",3.14,["Very",["Deep",["Array"]]],true,"It also supports nulls",null]'))) | ||
//const foo = new Map() | ||
//console.log(JSON.stringify(parseDynamicObject('{"hello":"world"}'))) | ||
// @ts-ignore | ||
@json | ||
class Test { | ||
stuff: string | ||
things: i32 | ||
} | ||
const test: Test = { | ||
stuff: "hi", | ||
things: 42 | ||
} | ||
console.log(stringify(JSON.stringify(test))) | ||
console.log(removeJSONWhitespace('{"stuff":"hi", "things":42}')) | ||
console.log(stringify(JSON.stringify(JSON.parse<Test>('{"stuff":"hi", "things":42}')))) | ||
const parsed = JSON.parse<Player>(stringified) | ||
// { firstName: "Emmet", lastName: "West", "lastActive": [8,27,2022], age: 23 } | ||
console.log(`Parsed: ${JSON.stringify(parsed)}`) |
{ | ||
"name": "json-as", | ||
"version": "0.2.6", | ||
"version": "0.4.0", | ||
"description": "JSON encoder/decoder for AssemblyScript", | ||
"types": "assembly/index.ts", | ||
"ascMain": "assembly/index.ts", | ||
"author": "JairusSW", | ||
"author": "Jairus Tanaka", | ||
"contributors": [ | ||
"DogWhich" | ||
], | ||
"license": "MIT", | ||
"scripts": { | ||
"build:transform": "tsc -w -p ./transform", | ||
"build:test": "asc assembly/test.ts --transform ./transform --target test --explicitStart", | ||
"test": "node --experimental-wasi-unstable-preview1 ./tests/test", | ||
"bench:build": "asc assembly/bench.ts --runtime incremental --transform ./transform --target bench --explicitStart", | ||
"bench:node": "node --experimental-wasi-unstable-preview1 ./bench/bench", | ||
"bench:wasmtime": "wasmtime ./bench/output/bench.wasm", | ||
"bench:lunatic": "lunatic ./bench/output/bench.wasm", | ||
"asbuild:untouched": "asc assembly/index.ts --target debug", | ||
"asbuild:optimized": "asc assembly/index.ts --target release", | ||
"asbuild": "yarn asbuild:untouched && yarn asbuild:optimized" | ||
"bench:astral": "astral", | ||
"build:test": "asc assembly/test.ts --target test", | ||
"build:transform": "tsc -p ./transform", | ||
"test:wasmtime": "wasmtime ./build/test.wasm", | ||
"test:lunatic": "lunatic ./build/test.wasm", | ||
"test:wasm3": "wasm3 ./build/test.wasm" | ||
}, | ||
"devDependencies": { | ||
"@as-pect/cli": "^6.2.4", | ||
"@assemblyscript/loader": "^0.19.10", | ||
"@serial-as/json": "^1.0.2", | ||
"@types/jest": "^27.0.2", | ||
"@types/line-column": "^1.0.0", | ||
"as-base64": "^0.2.0", | ||
"as-bignum": "^0.2.18", | ||
"@as-tral/cli": "^1.1.1", | ||
"as-console": "^6.0.2", | ||
"as-variant": "^0.2.1", | ||
"as-wasi": "^0.4.6", | ||
"asbuild": "^0.2.0", | ||
"assemblyscript": "^0.19.18", | ||
"assemblyscript-json": "^1.1.0", | ||
"jest": "^27.3.1", | ||
"kati": "^0.6.2", | ||
"lerna": "^4.0.0", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^27.0.7", | ||
"ts-node": "^10.4.0", | ||
"typescript": "^4.4.4" | ||
"assemblyscript": "^0.20.7", | ||
"assemblyscript-prettier": "^1.0.2", | ||
"benchmark": "^2.1.4", | ||
"microtime": "^3.0.0", | ||
"typescript": "^4.7.2" | ||
}, | ||
"dependencies": { | ||
"as-string-sink": "^0.4.2" | ||
"as-string-sink": "^0.5.0", | ||
"as-variant": "^0.3.0", | ||
"visitor-as": "^0.10.0" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/aspkg/as-json.git" | ||
"url": "git+https://github.com/JairusSW/as-json.git" | ||
}, | ||
@@ -54,8 +41,10 @@ "keywords": [ | ||
"serialize", | ||
"deserialize" | ||
"deserialize", | ||
"dynamic" | ||
], | ||
"bugs": { | ||
"url": "https://github.com/aspkg/as-json/issues" | ||
"url": "https://github.com/JairusSW/as-json/issues" | ||
}, | ||
"homepage": "https://github.com/aspkg/as-json#readme" | ||
"homepage": "https://github.com/JairusSW/as-json#readme", | ||
"type": "module" | ||
} |
151
README.md
# AS-JSON | ||
**JSON encoder/decoder for AssemblyScript** | ||
**JSON serializer/deserializer for AssemblyScript** | ||
## Installation | ||
@@ -8,3 +9,8 @@ | ||
~ npm install json-as | ||
~ yarn add json-as | ||
~ bun install json-as | ||
``` | ||
Add the transform to your `asc` command | ||
```bash | ||
@@ -14,115 +20,62 @@ --transform json-as/transform | ||
## Support | ||
- ✅ Objects | ||
- ✅ Arrays | ||
- ✅ Numbers | ||
- ✅ Integers | ||
- ✅ Null | ||
- ✅ Dynamic Arrays | ||
- ✅ Dynamic Types | ||
- ✅ Dynamic Objects | ||
- ✅ Whitespace | ||
Or, add it to `asconfig.json` | ||
## Usage | ||
```js | ||
import { JSON } from 'json-as' | ||
``` | ||
**Object** | ||
```js | ||
@json | ||
class JSONSchema { | ||
firstName: string | ||
lastName: string | ||
age: i32 | ||
{ | ||
"options": { | ||
"transform": "json-as/transform" | ||
} | ||
} | ||
const data: JSONSchema { | ||
firstName: 'Jairus', | ||
lastName: 'Tanaka', | ||
age: 14 | ||
} | ||
const stringified = JSON.stringify(data) | ||
// '{"firstName":"Jairus","lastName":"Tanaka","age":14}' | ||
const parsed = JSON.parse<JSONSchema>(stringified) | ||
// { firstName: "Jairus", lastName: "Tanaka", age: 14 } | ||
``` | ||
**Array** | ||
## Support | ||
```js | ||
const stringified = JSON.stringify(['Hello', 'World']) | ||
// '["Hello","World"]' | ||
- ✅ Objects (Supported) | ||
- ✅ Arrays (Supported) | ||
- ✅ Numbers (Supported) | ||
- ✅ Integers (Supported) | ||
- ✅ Null (Supported) | ||
- ❌ Dynamic Variants (Not supported) | ||
const parsed = JSON.parse<JSONSchema>(stringified) | ||
// ["Hello", "World"] | ||
``` | ||
## Usage | ||
**Float** | ||
```js | ||
const stringified = JSON.stringify(3.14) | ||
// '3.14' | ||
import { JSON } from "json-as"; | ||
const parsed = JSON.parse<f64>(stringified) | ||
// 3.14 | ||
``` | ||
@json | ||
class Vec2 { | ||
x: f32 | ||
y: f32 | ||
} | ||
@json | ||
class Player { | ||
firstName: string | ||
lastName: string | ||
lastActive: i32[] | ||
age: i32 | ||
pos: Vec2 | ||
} | ||
**Integer** | ||
const data: Player = { | ||
firstName: "Emmet", | ||
lastName: "West", | ||
lastActive: [8, 27, 2022], | ||
age: 23, | ||
pos: { | ||
x: -3.4, | ||
y: 1.2 | ||
} | ||
} | ||
```js | ||
const stringified = JSON.stringify(14) | ||
// '14' | ||
const stringified = JSON.stringify<Player>(data); | ||
// '{"firstName":"Emmet","lastName":"West","lastActive":[8,27,2022],"age":23}' | ||
console.log(`Stringified: ${stringified}`); | ||
const parsed = JSON.parse<i32>(stringified) | ||
// 14 | ||
const parsed = JSON.parse<Player>(stringified) | ||
// { firstName: "Emmet", lastName: "West", "lastActive": [8,27,2022], age: 23 } | ||
console.log(`Parsed: ${JSON.stringify(parsed)}`) | ||
``` | ||
**Boolean** | ||
## Issues | ||
```js | ||
const stringified = JSON.stringify(true) | ||
// 'true' | ||
const parsed = JSON.parse<boolean>(stringified) | ||
// true | ||
``` | ||
**Bool** | ||
```js | ||
const stringified = JSON.stringify(true) | ||
// 'true' | ||
const parsed = JSON.parse<bool>(stringified) | ||
// true | ||
``` | ||
**Null** | ||
```js | ||
const stringified = JSON.stringify(null) | ||
// 'null' | ||
const parsed = JSON.parse(stringified) | ||
// null | ||
``` | ||
## Benchmarks | ||
``` | ||
AS-JSON Stringify String: ~4191267.51 ops/s | 23.86ms | ||
AS-JSON Parse String: ~6218119.99 ops/s | 16.08ms | ||
AS-JSON Stringify Integer: ~13775012.61 ops/s | 7.26ms | ||
AS-JSON Parse Integer: ~55061164.13 ops/s | 1.82ms | ||
AS-JSON Stringify Float: ~7739399.89 ops/s | 12.92ms | ||
AS-JSON Parse Float: ~37522902.16 ops/s | 2.67ms | ||
AS-JSON Stringify Boolean: ~615015015.02 ops/s | 0.16ms | ||
AS-JSON Parse Boolean: ~93901879.87 ops/s | 1.06ms | ||
AS-JSON Stringify Array: ~2380329.74 ops/s | 42.01ms | ||
AS-JSON Parse Array: ~6258786.14 ops/s | 15.98ms | ||
AS-JSON Stringify Object: ~5245632.91 ops/s | 19.06ms | ||
AS-JSON Parse Object: ~1328576.06 ops/s | 75.27ms | ||
``` | ||
Please submit an issue to https://github.com/JairusSW/as-json/issues if you find anything wrong with this library |
@@ -1,4 +0,4 @@ | ||
const assert = require("assert"); | ||
const myModule = require(".."); | ||
assert.strictEqual(myModule.add(1, 2), 3); | ||
import assert from "assert"; | ||
import { add } from "../build/debug.js"; | ||
assert.strictEqual(add(1, 2), 3); | ||
console.log("ok"); |
const fs = require("fs"); | ||
const loader = require("@assemblyscript/loader"); | ||
const { WASI } = require('wasi') | ||
const wasiOptions = {} | ||
const wasi = new WASI(wasiOptions) | ||
const { WASI } = require("wasi"); | ||
const ConsoleImport = require('as-console/imports') | ||
const Console = new ConsoleImport() | ||
const wasiOptions = {}; | ||
const wasi = new WASI(wasiOptions); | ||
const imports = { | ||
wasi_snapshot_preview1: wasi.wasiImport | ||
wasi_snapshot_preview1: wasi.wasiImport, | ||
...Console.wasmImports | ||
}; | ||
const wasmModule = loader.instantiateSync(fs.readFileSync(__dirname + "/output/test.wasm"), imports); | ||
wasi.start(wasmModule) | ||
const wasmModule = loader.instantiateSync( | ||
fs.readFileSync(__dirname + "/output/test.wasm"), | ||
imports | ||
); | ||
Console.wasmExports = wasmModule.exports | ||
wasi.start(wasmModule); |
@@ -1,95 +0,29 @@ | ||
"use strict"; | ||
const as_1 = require("visitor-as/as"); | ||
const visitor_as_1 = require("visitor-as"); | ||
const utils_1 = require("visitor-as/dist/utils"); | ||
function getTypeName(type) { | ||
let _type = (0, utils_1.getName)(type); | ||
const OR_NULL = /\|.*null/; | ||
if (type.isNullable && !OR_NULL.test(_type)) { | ||
_type = `${_type} | null`; | ||
import { ClassDecorator, registerDecorator } from "visitor-as/dist/decorator.js"; | ||
import { getName } from "visitor-as/dist/utils.js"; | ||
import { SimpleParser } from "visitor-as/dist/index.js"; | ||
class AsJSONTransform extends ClassDecorator { | ||
constructor() { | ||
super(...arguments); | ||
this.sources = []; | ||
this.encodeStmts = new Map(); | ||
this.decodeCode = new Map(); | ||
} | ||
return _type; | ||
} | ||
// Replace Next Line | ||
const replaceNextLineRegex = /^\W*\/\/ <replace next line>.*$/gm; | ||
class JSONTransformer extends visitor_as_1.BaseVisitor { | ||
currentClass; | ||
encodeStmts = new Map(); | ||
decodeCode = new Map(); | ||
lastType = ''; | ||
sources = []; | ||
globalStatements = []; | ||
replaceNextLines = new Set(); | ||
visitObjectLiteralExpression(node) { | ||
const keys = node.names; | ||
const values = node.values; | ||
const replacer = visitor_as_1.SimpleParser.parseExpression(`new Object()`); | ||
for (const key of keys) { | ||
} | ||
} | ||
visitElementAccessExpression(node) { | ||
super.visitElementAccessExpression(node); | ||
if ((0, utils_1.toString)(node.expression) === 'o') { | ||
// Should be like if (node.expression.type.text === "Object") { | ||
const replacer = visitor_as_1.SimpleParser.parseExpression(`u32(changetype<usize>(${(0, utils_1.toString)(node.elementExpression)}))`); | ||
node.elementExpression = replacer; | ||
this.sources.push(replacer.range.source); | ||
} | ||
} | ||
visitArrayLiteralExpression(node) { | ||
super.visitArrayLiteralExpression(node); | ||
if (isanyArray(node)) { | ||
for (let i = 0; i < node.elementExpressions.length; i++) { | ||
const expr = node.elementExpressions[i]; | ||
// @ts-ignore | ||
let replacement; | ||
// @ts-ignore | ||
if (expr.elementExpressions) { | ||
// @ts-ignore | ||
this.convertToAnyArray(expr.elementExpressions); | ||
} | ||
// @ts-ignore | ||
replacement = visitor_as_1.SimpleParser.parseExpression(`unknown.wrap(${(0, utils_1.toString)(expr)})`); | ||
node.elementExpressions[i] = replacement; | ||
this.sources.push(replacement.range.source); | ||
} | ||
} | ||
} | ||
convertToAnyArray(exprs) { | ||
for (let i = 0; i < exprs.length; i++) { | ||
const expr = exprs[i]; | ||
// @ts-ignore | ||
let replacement; | ||
// @ts-ignore | ||
if (expr.elementExpressions) { | ||
// @ts-ignore | ||
this.convertToAnyArray(expr.elementExpressions); | ||
} | ||
// @ts-ignore | ||
replacement = visitor_as_1.SimpleParser.parseExpression(`unknown.wrap(${(0, utils_1.toString)(expr)})`); | ||
exprs[i] = replacement; | ||
this.sources.push(replacement.range.source); | ||
} | ||
} | ||
visitMethodDeclaration(node) { } | ||
visitFieldDeclaration(node) { | ||
super.visitFieldDeclaration(node); | ||
const name = (0, utils_1.toString)(node.name); | ||
const name = getName(node); | ||
if (!node.type) { | ||
throw new Error(`Field ${name} is missing a type declaration`); | ||
} | ||
const type = getTypeName(node.type); | ||
if (this.currentClass) { | ||
const className = this.currentClass.name.text; | ||
if (!this.encodeStmts.has(className)) | ||
this.encodeStmts.set(className, []); | ||
if (!this.decodeCode.has(className)) | ||
this.decodeCode.set(className, []); | ||
// @ts-ignore | ||
this.encodeStmts.get(className).push(`this.__encoded += '' + '"' + '${name}' + '"' + ':' + JSON.stringify<${type}>(this.${name}) + ',';`); | ||
// @ts-ignore | ||
this.decodeCode.get(className).push(`${name}: JSON.parse<${type}>(unchecked(values.get('${name}'))),\n`); | ||
} | ||
const type = getName(node.type); | ||
const className = this.currentClass.name.text; | ||
if (!this.encodeStmts.has(className)) | ||
this.encodeStmts.set(className, []); | ||
if (!this.decodeCode.has(className)) | ||
this.decodeCode.set(className, []); | ||
// @ts-ignore | ||
this.encodeStmts.get(className).push(`this.__JSON_Serialized += '' + '"' + '${name}' + '"' + ':' + JSON.stringify<${type}>(this.${name}) + ',';`); | ||
// @ts-ignore | ||
this.decodeCode.get(className).push(`${name}: JSON.parse<${type}>(values.get("${name}")),\n`); | ||
} | ||
visitClassDeclaration(node) { | ||
super.visitClassDeclaration(node); | ||
if (!node.members) { | ||
@@ -99,16 +33,17 @@ return; | ||
this.currentClass = node; | ||
const name = (0, utils_1.getName)(node); | ||
const name = getName(node); | ||
this.encodeStmts.delete(name); | ||
this.decodeCode.delete(name); | ||
this.visit(node.members); | ||
const encodedProp = `__encoded: string = ''`; | ||
let encodeMethod = ``; | ||
const serializedProp = `__JSON_Serialized: string = "";`; | ||
let serializeFunc = ``; | ||
if (this.encodeStmts.has(name) && this.encodeStmts.get(name)) { | ||
encodeMethod = ` | ||
__encode(): void { | ||
if (!this.__encoded) { | ||
serializeFunc = ` | ||
__JSON_Serialize(): string { | ||
if (!this.__JSON_Serialized) { | ||
${ // @ts-ignore | ||
this.encodeStmts.get(name).join("\n")}; | ||
this.__encoded = this.__encoded.slice(0, this.__encoded.length - 1) | ||
this.__JSON_Serialized = "{" + this.__JSON_Serialized.slice(0, this.__JSON_Serialized.length - 1) + "}"; | ||
} | ||
return this.__JSON_Serialized; | ||
} | ||
@@ -118,66 +53,28 @@ `; | ||
else { | ||
encodeMethod = ` | ||
__encode(): void {} | ||
serializeFunc = ` | ||
__JSON_Serialize(): string { | ||
return "{}"; | ||
} | ||
`; | ||
} | ||
const decodeMethod = ` | ||
__decode(values: Map<string, string>): ${name} { | ||
const decoded: ${name} = { | ||
const deserializeFunc = ` | ||
__JSON_Deserialize(values: Map<string, string>): ${name} { | ||
return { | ||
${ // @ts-ignore | ||
this.decodeCode.get(name) ? this.decodeCode.get(name).join("") : ''} | ||
this.decodeCode.get(name) ? this.decodeCode.get(name).join("") : ""} | ||
} | ||
return decoded | ||
} | ||
`; | ||
const encodedPropMember = visitor_as_1.SimpleParser.parseClassMember(encodedProp, node); | ||
node.members.push(encodedPropMember); | ||
const encodeMember = visitor_as_1.SimpleParser.parseClassMember(encodeMethod, node); | ||
node.members.push(encodeMember); | ||
const decodeMember = visitor_as_1.SimpleParser.parseClassMember(decodeMethod, node); | ||
node.members.push(decodeMember); | ||
//console.log(serializedProp, serializeFunc, deserializeFunc) | ||
const serializedProperty = SimpleParser.parseClassMember(serializedProp, node); | ||
node.members.push(serializedProperty); | ||
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node); | ||
node.members.push(serializeMethod); | ||
const deserializeMethod = SimpleParser.parseClassMember(deserializeFunc, node); | ||
node.members.push(deserializeMethod); | ||
} | ||
static visit(node) { | ||
new JSONTransformer().visit(node); | ||
get name() { | ||
return "json"; | ||
} | ||
visitSource(source) { | ||
this.globalStatements = []; | ||
super.visitSource(source); | ||
} | ||
} | ||
function isanyArray(node) { | ||
if (node.elementExpressions.length === 0) | ||
return false; | ||
const firstKind = node.elementExpressions[0]?.kind; | ||
const isBoolean = ((0, utils_1.toString)(node.elementExpressions[0]) === 'true' || (0, utils_1.toString)(node.elementExpressions[0]) === 'false'); | ||
for (const chunk of node.elementExpressions) { | ||
if (isBoolean) { | ||
if ((0, utils_1.toString)(chunk) !== 'true' || (0, utils_1.toString)(chunk) !== 'false') | ||
true; | ||
} | ||
else if (chunk.kind !== firstKind) | ||
return true; | ||
} | ||
return false; | ||
} | ||
module.exports = class MyTransform extends as_1.Transform { | ||
// Trigger the transform after parse. | ||
afterParse(parser) { | ||
// Create new transform | ||
const transformer = new JSONTransformer(); | ||
// Loop over every source | ||
for (const source of parser.sources) { | ||
// Ignore all lib (std lib). Visit everything else. | ||
if (!source.isLibrary && !source.internalPath.startsWith(`~lib/`)) { | ||
transformer.visit(source); | ||
} | ||
} | ||
let i = 0; | ||
for (const source of transformer.sources) { | ||
//source.internalPath += `${i++}.ts` | ||
if (i === 0) { | ||
parser.sources.push(source); | ||
i++; | ||
} | ||
} | ||
} | ||
}; | ||
export default registerDecorator(new AsJSONTransform()); |
{ | ||
"main": "./lib/index.js" | ||
} | ||
"name": "@json-as/transform", | ||
"version": "0.4.0", | ||
"description": "JSON encoder/decoder for AssemblyScript", | ||
"main": "./lib/index.js", | ||
"author": "Jairus Tanaka", | ||
"contributors": [ | ||
"DogWhich" | ||
], | ||
"license": "MIT", | ||
"scripts": {}, | ||
"devDependencies": {}, | ||
"dependencies": {}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/JairusSW/as-json.git" | ||
}, | ||
"keywords": [ | ||
"assemblyscript", | ||
"json", | ||
"serialize", | ||
"deserialize", | ||
"dynamic" | ||
], | ||
"bugs": { | ||
"url": "https://github.com/JairusSW/as-json/issues" | ||
}, | ||
"homepage": "https://github.com/JairusSW/as-json#readme", | ||
"type": "module", | ||
"exports": "./lib/index.js" | ||
} |
{ | ||
"compilerOptions": { | ||
/* Visit https://aka.ms/tsconfig.json to read more about this file */ | ||
/* Basic Options */ | ||
// "incremental": true, /* Enable incremental compilation */ | ||
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ | ||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ | ||
// "lib": [], /* Specify library files to be included in the compilation. */ | ||
// "allowJs": true, /* Allow javascript files to be compiled. */ | ||
// "checkJs": true, /* Report errors in .js files. */ | ||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ | ||
"declaration": false, /* Generates corresponding '.d.ts' file. */ | ||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||
"sourceMap": false, /* Generates corresponding '.map' file. */ | ||
// "outFile": "./", /* Concatenate and emit output to single file. */ | ||
"outDir": "./lib/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ | ||
// "composite": true, /* Enable project compilation */ | ||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ | ||
// "removeComments": true, /* Do not emit comments to output. */ | ||
// "noEmit": true, /* Do not emit outputs. */ | ||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */ | ||
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ | ||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ | ||
/* Strict Type-Checking Options */ | ||
"strict": true, /* Enable all strict type-checking options. */ | ||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'unknown' type. */ | ||
"strictNullChecks": true, /* Enable strict null checks. */ | ||
"strictFunctionTypes": true, /* Enable strict checking of function types. */ | ||
"strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ | ||
"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ | ||
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'unknown' type. */ | ||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ | ||
/* Additional Checks */ | ||
"noUnusedLocals": true, /* Report errors on unused locals. */ | ||
"noUnusedParameters": true, /* Report errors on unused parameters. */ | ||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ | ||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ | ||
"noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ | ||
"noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ | ||
/* Module Resolution Options */ | ||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ | ||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ | ||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ | ||
// "typeRoots": [], /* List of folders to include type definitions from. */ | ||
// "types": [], /* Type declaration files to be included in compilation. */ | ||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ | ||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ | ||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ | ||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ | ||
/* Source Map Options */ | ||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ | ||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ | ||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ | ||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||
/* Experimental Options */ | ||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ | ||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ | ||
/* Advanced Options */ | ||
"skipLibCheck": true, /* Skip type checking of declaration files. */ | ||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ | ||
} | ||
"compilerOptions": { | ||
/* Visit https://aka.ms/tsconfig.json to read more about this file */ | ||
/* Basic Options */ | ||
// "incremental": true, /* Enable incremental compilation */ | ||
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, | ||
"module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, | ||
// "lib": [], /* Specify library files to be included in the compilation. */ | ||
// "allowJs": true, /* Allow javascript files to be compiled. */ | ||
// "checkJs": true, /* Report errors in .js files. */ | ||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ | ||
"declaration": false /* Generates corresponding '.d.ts' file. */, | ||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||
"sourceMap": false /* Generates corresponding '.map' file. */, | ||
// "outFile": "./", /* Concatenate and emit output to single file. */ | ||
"outDir": "./lib/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, | ||
// "composite": true, /* Enable project compilation */ | ||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ | ||
// "removeComments": true, /* Do not emit comments to output. */ | ||
// "noEmit": true, /* Do not emit outputs. */ | ||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */ | ||
"downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, | ||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ | ||
/* Strict Type-Checking Options */ | ||
"strict": true /* Enable all strict type-checking options. */, | ||
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'Unknown' type. */, | ||
"strictNullChecks": true /* Enable strict null checks. */, | ||
"strictFunctionTypes": true /* Enable strict checking of function types. */, | ||
"strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */, | ||
"strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */, | ||
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'Unknown' type. */, | ||
"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, | ||
/* Additional Checks */ | ||
"noUnusedLocals": true /* Report errors on unused locals. */, | ||
"noUnusedParameters": true /* Report errors on unused parameters. */, | ||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */, | ||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ | ||
"noUncheckedIndexedAccess": true /* Include 'undefined' in index signature results */, | ||
"noPropertyAccessFromIndexSignature": true /* Require undeclared properties from index signatures to use element accesses. */, | ||
/* Module Resolution Options */ | ||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ | ||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ | ||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ | ||
// "typeRoots": [], /* List of folders to include type definitions from. */ | ||
// "types": [], /* Type declaration files to be included in compilation. */ | ||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ | ||
"esModuleInterop": false /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, | ||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ | ||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ | ||
/* Source Map Options */ | ||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ | ||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ | ||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ | ||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||
/* Experimental Options */ | ||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ | ||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ | ||
/* Advanced Options */ | ||
"skipLibCheck": true /* Skip type checking of declaration files. */, | ||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
7
-65%18
12.5%2
-50%Yes
NaN44786
-39.43%3
200%1134
-39.55%79
-37.3%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
Updated