Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9,544 changes: 9,139 additions & 405 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
],
"homepage": "https://github.com/jtenner/ason#readme",
"devDependencies": {
"@as-pect/cli": "^6.1.1",
"assemblyscript": "^0.18.31",
"@as-pect/cli": "^6.2.4",
"assemblyscript": "^0.19.3",
"lerna": "^4.0.0",
"npm-run-all": "^4.1.5",
"typescript": "^4.2.4"
"typescript": "^4.3.4"
},
"dependencies": {
"visitor-as": "^0.5.0"
"visitor-as": "^0.6.0"
}
}
16 changes: 10 additions & 6 deletions packages/assembly/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ function getObjectSize<T>(value: T): usize {
function getObjectType(value: usize): u32 {
return changetype<OBJECT>(value - TOTAL_OVERHEAD).rtId;
}

// This function is just for type sanity. It should never be called.
// @as-covers: ignore
function __unusedVoidCallDeserialize<T>(value: T): bool {
let buffer: StaticArray<u8>;
// @ts-ignore
Expand Down Expand Up @@ -147,13 +148,16 @@ export namespace ASON {
// custom serialization
let temp: StaticArray<u8>;
// @ts-ignore: safe compile time check
// @as-covers: ignore
if (!isDefined(temp = value.__asonSerialize())) {
ERROR("__asonSerialize method must return a StaticArray<u8>");
}
// @ts-ignore: safe compile time check
// @as-covers: ignore
if (!isDefined(__unusedVoidCallDeserialize(value))) {
ERROR("__asonDeserialize method must accept a StaticArray<u8>");
}
// @as-covers: ignore
if (!isReference(value)) {
ERROR("Custom ASON serializtion can only be performed on a reference.");
}
Expand Down Expand Up @@ -481,11 +485,7 @@ export namespace ASON {
public putField<U>(entryId: u32, value: U, offset: usize): void {
if (isReference(value)) {
if (changetype<usize>(value) != 0) {
if (isNullable(value)) {
this.putLink(this.put(value!), entryId, offset);
} else {
this.putLink(this.put(value), entryId, offset);
}
this.putLink(this.put(value), entryId, offset);
}
return;
}
Expand Down Expand Up @@ -975,6 +975,7 @@ export namespace ASON {
);
changetype<Map<Dummy, u64>>(parent).set(key, value);
break;
// @as-covers: ignore
}
default: assert(false);
}
Expand Down Expand Up @@ -1031,6 +1032,7 @@ export namespace ASON {
);
changetype<Map<string, u64>>(parent).set(key, value);
break;
// @as-covers: ignore
}
default: assert(false);
}
Expand Down Expand Up @@ -1097,10 +1099,12 @@ export namespace ASON {
);
}
break;
// @as-covers: ignore
}
default: assert(false);
}
break;
// @as-covers: ignore
}
default: assert(false);
}
Expand Down
59 changes: 51 additions & 8 deletions packages/assembly/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/assembly/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@ason/transform": "^0.1.1"
},
"devDependencies": {
"assemblyscript": "^0.18.31"
"assemblyscript": "^0.19.3"
},
"scripts": {
"asbuild:untouched": "asc assembly/index.ts --target debug",
Expand Down
18 changes: 1 addition & 17 deletions packages/test/as-pect.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,7 @@ module.exports = {
instance = instantiateSync(binary, createImports(myImports));
return instance;
},
/**
* Add a custom reporter here if you want one. The following example is in typescript.
*
* @example
* import { TestReporter, TestGroup, TestResult, TestContext } from "as-pect";
*
* export class CustomReporter extends TestReporter {
* // implement each abstract method here
* public abstract onStart(suite: TestContext): void;
* public abstract onGroupStart(group: TestGroup): void;
* public abstract onGroupFinish(group: TestGroup): void;
* public abstract onTestStart(group: TestGroup, result: TestResult): void;
* public abstract onTestFinish(group: TestGroup, result: TestResult): void;
* public abstract onFinish(suite: TestContext): void;
* }
*/
// reporter: new CustomReporter(),
coverage: ["../assembly/index.ts"],
/**
* Specify if the binary wasm file should be written to the file system.
*/
Expand Down
115 changes: 110 additions & 5 deletions packages/test/assembly/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ describe("ASON test suite", () => {
test("serialize null", checkSerializeNull);
test("static array of references", staticArrayOfReferences);
test("static array data", staticArrayData);
test("nullable array data segments", testArrayDataSegments);
test("nullable array references", testArrayNullableReferences);
test("reference with nullable references", testReferenceWithNullableReferences);
test("complex array circular", arrayOfSameReferenceWithCircular);
test("complex array with circular reference", arrayOfSameReferenceWithActualCircular);
test("serialize numeric values", serializeNumericValues);
test("set of strings", setOfStrings);
test("set of integers", setOfIntegers);
test("set of references", setOfReferences);
test("custom", testCustom);
test("customVector", testCustomVectorSerialization);
test("really long static strings", testStaticStrings);
Expand All @@ -42,35 +47,72 @@ describe("ASON test suite", () => {
test("funtions", testCallbacks);

describe("map", () => {
test("int to int maps", () => { testMap<u8, u8>([1, 2, 3], [3, 6, 9]); });
test("string to int maps", () => { testMap<string, u8>(["one", "two", "three"], [3, 6, 9]); });
test("int to int maps", () => {
testMap<u8, u8>([1, 2, 3], [3, 6, 9]);
testMap<u16, u16>([1, 2, 3], [3, 6, 9]);
testMap<u32, u32>([1, 2, 3], [3, 6, 9]);
testMap<u64, u64>([1, 2, 3], [3, 6, 9]);
});
test("signed int to int maps", () => {
testMap<i8, i8>([1, 2, 3], [3, 6, 9]);
testMap<i16, i16>([1, 2, 3], [3, 6, 9]);
testMap<i32, i32>([1, 2, 3], [3, 6, 9]);
testMap<i64, i64>([1, 2, 3], [3, 6, 9]);
});
test("string to int maps", () => {
testMap<string, u8>(["one", "two", "three"], [3, 6, 9]);
testMap<string, u16>(["one", "two", "three"], [3, 6, 9]);
testMap<string, u32>(["one", "two", "three"], [3, 6, 9]);
testMap<string, u64>(["one", "two", "three"], [3, 6, 9]);
});
test("string to object maps", () => { testMap<string, Vec3>(["one", "two", "three"], [new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)]); })
test("different sized int to int maps", () => { testMap<i64, u8>([-1384328, 2, -3], [3, 6, 9]); });
test("float to int maps", () => { testMap<f32, u8>([-1.01, 4.0, 341.44], [4, 5, 7]); });
test("different sized float to float maps", () => { testMap<f32, f64>([1.44, -0.00000425, 3334445], [9.8, 756, 0.00000000000000004478]); });
test("object to int maps", () => { testMap<Vec3, u8>([new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)], [3, 6, 9]); });
test("object to int maps", () => {
testMap<Vec3, u8>([new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)], [3, 6, 9]);
testMap<Vec3, u16>([new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)], [3, 6, 9]);
testMap<Vec3, u32>([new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)], [3, 6, 9]);
testMap<Vec3, u64>([new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)], [3, 6, 9]);
});
test("float to string maps, with emoji", () => { testMap<f32, string>([2.1, 3.1415926, 2.71828], ["TwoAndABit", "Pi", "🇪"]); });
test("negative float to string maps", () => { testMap<f32, string>([-11.4, -1.0, 8.000001],["Negative", "Floats", "Work"]); });
test("int to empty string maps", () => { testMap<u8, string>([1,2,3],["","",""]); });
test("int to complex object maps", () => {
let a1 = new A();
a1.a = 0.989;
let a2 = new A();
testMap<u8, A>([11, 1], [a1, a2]);
testMap<i8, A>([-1, 1], [a1, a2]);
});
test("object to object maps", () => {
testMap<Vec3, Vec3>([new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)],
[new Vec3(11, 12, 13), new Vec3(14, 15, 16), new Vec3(17, 18, 19)]);
});
test("int to complex object maps, with multiple and circular references", () => {
let a1 = new A();
a1.a = 0.989;
let a2 = new A();
a2.b.a = a1;
testMap<i8, A>([-1, 1, 2], [a1, a2, a1]);
testMap<u16, A>([11, 1, 2], [a1, a2, a1]);
testMap<i16, A>([-1, 1, 2], [a1, a2, a1]);
});
test("int to nullable object maps", () => {
let a1 = new A();
testMap<u32, A | null>([4, 11], [null, a1]);
testMap<i32, A | null>([4, -1], [null, a1]);
});
test("int to simple object maps", () => {
testMap<u64, Vec3>([3, 6, 9], [new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)]);
testMap<i64, Vec3>([3, 6, 9], [new Vec3(1, 2, 3), new Vec3(4, 5, 6), new Vec3(7, 8, 9)]);
})
test("infinite floats to float maps", () => { testMap<f32, f64>([Infinity],[44.44]); });
});
test("Major objects that should engage all parts of ASON", testHugeObject);
itThrows("when you attempt to deserialize an empty buffer into a non-nullable type", () => {
let buff = new StaticArray<u8>(0);
ASON.deserialize<Vec3>(buff);
});
});

function testBasicVectors(): void {
Expand Down Expand Up @@ -201,6 +243,40 @@ function staticArrayData(): void {
__collect();
}

function testArrayDataSegments(): void {
let a: Array<i32> | null = [1,2,3];
let buffer = ASON.serialize(a);
let b = ASON.deserialize<Array<i32> | null>(buffer);
expect(a).toStrictEqual(b);
}

function testArrayNullableReferences(): void {
let a: Array<Vec3> | null = new Array();
a!.push(new Vec3(3,1,4));
a!.push(new Vec3(1,6,8));

let buffer = ASON.serialize(a);
let b = ASON.deserialize<Array<Vec3> | null>(buffer);
expect(a).toStrictEqual(b);
}

class C {
onlything: D | null;
}
class D {
int: i32;
}

function testReferenceWithNullableReferences(): void {
let c: C = new C();
let d: D = new D();
c.onlything = d;

let buffer = ASON.serialize(c);
let c2 = ASON.deserialize<C>(buffer);
expect(c).toStrictEqual(c2);
}

class ArrayChild {
circular: Array<ArrayChild> | null;
}
Expand All @@ -219,6 +295,22 @@ function arrayOfSameReferenceWithCircular(): void {
__collect();
}

function arrayOfSameReferenceWithActualCircular(): void {
let child = new ArrayChild();
let a = [child, child, child, child, child, child];
child.circular = a;
let buff = ASON.serialize(a);
let b = ASON.deserialize<Array<ArrayChild>>(buff);

assert(a.length == b.length);
let first = b[0];
for (let i = 0; i < a.length; i++) {
assert(b[i] == first);
}
__collect();
}


function serializeNumericValues(): void {
assert(ASON.deserialize<f64>(ASON.serialize(<f64>3.14)) == 3.14);
assert(ASON.deserialize<i32>(ASON.serialize(64)) == 64);
Expand Down Expand Up @@ -257,6 +349,15 @@ function setOfIntegers(): void {
__collect();
}

function setOfReferences(): void {
let a = new Set<A>();
a.add(new A());
a.add(new A());

let value = ASON.deserialize<Set<A>>(ASON.serialize(a));
expect(a).toStrictEqual(value);
}

function testMap<TKey, TValue>(keys: StaticArray<TKey>, values: StaticArray<TValue>): void {
assert(keys.length == values.length);
let len = keys.length;
Expand Down Expand Up @@ -355,7 +456,7 @@ class übermenschObject {
e: i16[] = [];
f: A[] = [];
g: Array<String> = new Array<String>();
//h: funcref | null;
//h: ((G:string) => void) | null;
}

function testHugeObject(): void {
Expand All @@ -378,6 +479,10 @@ function testHugeObject(): void {
"I know a song that gets on everybody's nerves,",
"And this is how it goes:"
];
// TODO: We are aware that this will error.
//bigobj.h = (G: string): void => {
// trace(G);
//};

let buff = ASON.serialize(bigobj);
let b = ASON.deserialize<übermenschObject>(buff);
Expand Down
Loading