@as-pect/transform 7.0.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -26,13 +26,13 @@ import { djb2Hash } from "./hash.js";
|
|
|
26
26
|
export function createAddReflectedValueKeyValuePairsMember(classDeclaration) {
|
|
27
27
|
const range = classDeclaration.name.range;
|
|
28
28
|
// __aspectAddReflectedValueKeyValuePairs(reflectedValue: i32, seen: Map<usize, i32>, ignore: StaticArray<i64>): void
|
|
29
|
-
return TypeNode.createMethodDeclaration(TypeNode.createIdentifierExpression("__aspectAddReflectedValueKeyValuePairs", range), null, 256 /* CommonFlags.
|
|
29
|
+
return TypeNode.createMethodDeclaration(TypeNode.createIdentifierExpression("__aspectAddReflectedValueKeyValuePairs", range), null, 256 /* CommonFlags.Public */ | 262144 /* CommonFlags.Instance */ | (classDeclaration.isGeneric ? 131072 /* CommonFlags.GenericContext */ : 0), null, TypeNode.createFunctionType([
|
|
30
30
|
// reflectedValue: i32
|
|
31
|
-
TypeNode.createParameter(0 /* ParameterKind.
|
|
31
|
+
TypeNode.createParameter(0 /* ParameterKind.Default */, TypeNode.createIdentifierExpression("reflectedValue", range), createGenericTypeParameter("i32", range), null, range),
|
|
32
32
|
// seen: Map<usize, i32>
|
|
33
|
-
TypeNode.createParameter(0 /* ParameterKind.
|
|
33
|
+
TypeNode.createParameter(0 /* ParameterKind.Default */, TypeNode.createIdentifierExpression("seen", range), TypeNode.createNamedType(TypeNode.createSimpleTypeName("Map", range), [createGenericTypeParameter("usize", range), createGenericTypeParameter("i32", range)], false, range), null, range),
|
|
34
34
|
// ignore: i64[]
|
|
35
|
-
TypeNode.createParameter(0 /* ParameterKind.
|
|
35
|
+
TypeNode.createParameter(0 /* ParameterKind.Default */, TypeNode.createIdentifierExpression("ignore", range),
|
|
36
36
|
// Array<i64> -> i64[]
|
|
37
37
|
TypeNode.createNamedType(TypeNode.createSimpleTypeName("StaticArray", range), [createGenericTypeParameter("i64", range)], false, range), null, range),
|
|
38
38
|
],
|
|
@@ -52,10 +52,10 @@ function createAddReflectedValueKeyValuePairsFunctionBody(classDeclaration) {
|
|
|
52
52
|
// for each field declaration, generate a check
|
|
53
53
|
for (const member of classDeclaration.members) {
|
|
54
54
|
// if it's an instance member, regardless of access modifier
|
|
55
|
-
if (member.is(262144 /* CommonFlags.
|
|
55
|
+
if (member.is(262144 /* CommonFlags.Instance */)) {
|
|
56
56
|
switch (member.kind) {
|
|
57
57
|
// field declarations automatically get added
|
|
58
|
-
case 54 /* NodeKind.
|
|
58
|
+
case 54 /* NodeKind.FieldDeclaration */: {
|
|
59
59
|
const fieldDeclaration = member;
|
|
60
60
|
const hashValue = djb2Hash(member.name.text);
|
|
61
61
|
pushKeyValueIfStatement(body, member.name.text, hashValue, fieldDeclaration.range);
|
|
@@ -63,8 +63,8 @@ function createAddReflectedValueKeyValuePairsFunctionBody(classDeclaration) {
|
|
|
63
63
|
break;
|
|
64
64
|
}
|
|
65
65
|
// function declarations can be getters, check the get flag
|
|
66
|
-
case 58 /* NodeKind.
|
|
67
|
-
if (member.is(2048 /* CommonFlags.
|
|
66
|
+
case 58 /* NodeKind.MethodDeclaration */: {
|
|
67
|
+
if (member.is(2048 /* CommonFlags.Get */)) {
|
|
68
68
|
const methodDeclaration = member;
|
|
69
69
|
const hashValue = djb2Hash(member.name.text);
|
|
70
70
|
pushKeyValueIfStatement(body, member.name.text, hashValue, methodDeclaration.range);
|
|
@@ -106,7 +106,7 @@ function createIsDefinedIfStatement(nameHashes, range) {
|
|
|
106
106
|
TypeNode.createCallExpression(TypeNode.createPropertyAccessExpression(TypeNode.createIdentifierExpression("StaticArray", range), TypeNode.createIdentifierExpression("concat", range), range), null, [
|
|
107
107
|
TypeNode.createIdentifierExpression("ignore", range),
|
|
108
108
|
// [...propNames]
|
|
109
|
-
TypeNode.createAssertionExpression(1 /* AssertionKind.
|
|
109
|
+
TypeNode.createAssertionExpression(1 /* AssertionKind.As */, TypeNode.createArrayLiteralExpression(nameHashes.map((e) => TypeNode.createIntegerLiteralExpression(f64_as_i64(e), range)), range), TypeNode.createNamedType(TypeNode.createSimpleTypeName("StaticArray", range), [TypeNode.createNamedType(TypeNode.createSimpleTypeName("i64", range), null, false, range)], false, range), range),
|
|
110
110
|
], range),
|
|
111
111
|
], range)),
|
|
112
112
|
], range), null, range);
|
|
@@ -122,7 +122,7 @@ function createIsDefinedIfStatement(nameHashes, range) {
|
|
|
122
122
|
function pushKeyValueIfStatement(body, name, hashValue, range) {
|
|
123
123
|
body.push(
|
|
124
124
|
// if (!ignore.includes("propName")) { ... }
|
|
125
|
-
TypeNode.createIfStatement(TypeNode.createUnaryPrefixExpression(95 /* Token.
|
|
125
|
+
TypeNode.createIfStatement(TypeNode.createUnaryPrefixExpression(95 /* Token.Exclamation */,
|
|
126
126
|
// ignore.includes("propName")
|
|
127
127
|
TypeNode.createCallExpression(TypeNode.createPropertyAccessExpression(TypeNode.createIdentifierExpression("ignore", range), TypeNode.createIdentifierExpression("includes", range), range), null, [
|
|
128
128
|
// hashValue
|
|
@@ -8,14 +8,10 @@ import { TypeNode, } from "assemblyscript/dist/assemblyscript.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export function createStrictEqualsMember(classDeclaration) {
|
|
10
10
|
const range = classDeclaration.name.range;
|
|
11
|
-
// __aspectStrictEquals(
|
|
12
|
-
return TypeNode.createMethodDeclaration(TypeNode.createIdentifierExpression("__aspectStrictEquals", range), null, 256 /* CommonFlags.
|
|
13
|
-
//
|
|
14
|
-
createDefaultParameter("
|
|
15
|
-
? classDeclaration.typeParameters.map((node) => TypeNode.createNamedType(TypeNode.createSimpleTypeName(node.name.text, range), null, false, range))
|
|
16
|
-
: null, false, range),
|
|
17
|
-
//createGenericTypeParameter("this", range),
|
|
18
|
-
range),
|
|
11
|
+
// __aspectStrictEquals(rawRef: Object, stackA: usize[], stackB: usize[], ignore: StaticArray<i64>): bool
|
|
12
|
+
return TypeNode.createMethodDeclaration(TypeNode.createIdentifierExpression("__aspectStrictEquals", range), null, 256 /* CommonFlags.Public */ | 262144 /* CommonFlags.Instance */ | (classDeclaration.isGeneric ? 131072 /* CommonFlags.GenericContext */ : 0), null, TypeNode.createFunctionType([
|
|
13
|
+
// rawRef: Object,
|
|
14
|
+
createDefaultParameter("rawRef", TypeNode.createNamedType(TypeNode.createSimpleTypeName("Object", range), null, false, range), range),
|
|
19
15
|
// stack: usize[]
|
|
20
16
|
createDefaultParameter("stack", createArrayType("usize", range), range),
|
|
21
17
|
// cache: usize[]
|
|
@@ -52,13 +48,23 @@ function createStrictEqualsFunctionBody(classDeclaration) {
|
|
|
52
48
|
const body = new Array();
|
|
53
49
|
const range = classDeclaration.name.range;
|
|
54
50
|
const nameHashes = new Array();
|
|
51
|
+
const rawRef = TypeNode.createIdentifierExpression("rawRef", range);
|
|
52
|
+
const classType = TypeNode.createNamedType(TypeNode.createSimpleTypeName(classDeclaration.name.text, range), classDeclaration.isGeneric
|
|
53
|
+
? classDeclaration.typeParameters.map((node) => TypeNode.createNamedType(TypeNode.createSimpleTypeName(node.name.text, range), null, false, range))
|
|
54
|
+
: null, false, range);
|
|
55
|
+
// Check if the parameter is an instance of the class; return otherwise
|
|
56
|
+
body.push(TypeNode.createIfStatement(TypeNode.createUnaryPrefixExpression(95 /* Token.Exclamation */, TypeNode.createInstanceOfExpression(rawRef, classType, range), range), TypeNode.createReturnStatement(TypeNode.createFalseExpression(range), range), null, range));
|
|
57
|
+
// Cast rawRef into an instance of the class
|
|
58
|
+
body.push(TypeNode.createVariableStatement(null, [
|
|
59
|
+
TypeNode.createVariableDeclaration(TypeNode.createIdentifierExpression("ref", range), null, 8 /* CommonFlags.Const */, classType, TypeNode.createAssertionExpression(1 /* AssertionKind.As */, rawRef, classType, range), range)
|
|
60
|
+
], range));
|
|
55
61
|
// for each field declaration, generate a check
|
|
56
62
|
for (const member of classDeclaration.members) {
|
|
57
63
|
// if it's an instance member, regardless of access modifier
|
|
58
|
-
if (member.is(262144 /* CommonFlags.
|
|
64
|
+
if (member.is(262144 /* CommonFlags.Instance */)) {
|
|
59
65
|
switch (member.kind) {
|
|
60
66
|
// field declarations automatically get added
|
|
61
|
-
case 54 /* NodeKind.
|
|
67
|
+
case 54 /* NodeKind.FieldDeclaration */: {
|
|
62
68
|
const fieldDeclaration = member;
|
|
63
69
|
const hashValue = djb2Hash(member.name.text);
|
|
64
70
|
body.push(createStrictEqualsIfCheck(member.name.text, hashValue, fieldDeclaration.range));
|
|
@@ -66,8 +72,8 @@ function createStrictEqualsFunctionBody(classDeclaration) {
|
|
|
66
72
|
break;
|
|
67
73
|
}
|
|
68
74
|
// function declarations can be getters, check the get flag
|
|
69
|
-
case 58 /* NodeKind.
|
|
70
|
-
if (member.is(2048 /* CommonFlags.
|
|
75
|
+
case 58 /* NodeKind.MethodDeclaration */: {
|
|
76
|
+
if (member.is(2048 /* CommonFlags.Get */)) {
|
|
71
77
|
const methodDeclaration = member;
|
|
72
78
|
const hashValue = djb2Hash(member.name.text);
|
|
73
79
|
body.push(createStrictEqualsIfCheck(methodDeclaration.name.text, hashValue, methodDeclaration.name.range));
|
|
@@ -92,7 +98,7 @@ function createStrictEqualsFunctionBody(classDeclaration) {
|
|
|
92
98
|
* @param {Range} range - The source range for the given property.
|
|
93
99
|
*/
|
|
94
100
|
function createStrictEqualsIfCheck(name, hashValue, range) {
|
|
95
|
-
const equalsCheck = TypeNode.createBinaryExpression(76 /* Token.
|
|
101
|
+
const equalsCheck = TypeNode.createBinaryExpression(76 /* Token.Equals_Equals */,
|
|
96
102
|
// Reflect.equals(this.prop, ref.prop, stack, cache)
|
|
97
103
|
TypeNode.createCallExpression(
|
|
98
104
|
// Reflect.equals
|
|
@@ -109,7 +115,7 @@ function createStrictEqualsIfCheck(name, hashValue, range) {
|
|
|
109
115
|
TypeNode.createIdentifierExpression("cache", range),
|
|
110
116
|
], range), createPropertyAccess("Reflect", "FAILED_MATCH", range), range);
|
|
111
117
|
// !ignore.includes("prop")
|
|
112
|
-
const includesCheck = TypeNode.createUnaryPrefixExpression(95 /* Token.
|
|
118
|
+
const includesCheck = TypeNode.createUnaryPrefixExpression(95 /* Token.Exclamation */,
|
|
113
119
|
// ignore.includes("prop")
|
|
114
120
|
TypeNode.createCallExpression(
|
|
115
121
|
// ignore.includes
|
|
@@ -119,7 +125,7 @@ function createStrictEqualsIfCheck(name, hashValue, range) {
|
|
|
119
125
|
// if (Reflect.equals(this.prop, ref.prop, stack, cache) === Reflect.FAILED_MATCH) return false;
|
|
120
126
|
return TypeNode.createIfStatement(
|
|
121
127
|
// Reflect.equals(this.prop, ref.prop, stack, cache) === Reflect.FAILED_MATCH
|
|
122
|
-
TypeNode.createBinaryExpression(97 /* Token.
|
|
128
|
+
TypeNode.createBinaryExpression(97 /* Token.Ampersand_Ampersand */, includesCheck, equalsCheck, range),
|
|
123
129
|
// return false;
|
|
124
130
|
TypeNode.createReturnStatement(TypeNode.createFalseExpression(range), range), null, range);
|
|
125
131
|
}
|
|
@@ -131,7 +137,7 @@ function createStrictEqualsIfCheck(name, hashValue, range) {
|
|
|
131
137
|
* @param {Range} range - The source range of the parameter.
|
|
132
138
|
*/
|
|
133
139
|
function createDefaultParameter(name, typeNode, range) {
|
|
134
|
-
return TypeNode.createParameter(0 /* ParameterKind.
|
|
140
|
+
return TypeNode.createParameter(0 /* ParameterKind.Default */, TypeNode.createIdentifierExpression(name, range), typeNode, null, range);
|
|
135
141
|
}
|
|
136
142
|
/**
|
|
137
143
|
* This method creates a single property access and passes the given range to the AST.
|
|
@@ -156,7 +162,7 @@ function createSuperCallStatement(classDeclaration, nameHashes) {
|
|
|
156
162
|
const ifStatement = TypeNode.createIfStatement(TypeNode.createCallExpression(TypeNode.createIdentifierExpression("isDefined", range), null, [
|
|
157
163
|
TypeNode.createPropertyAccessExpression(TypeNode.createSuperExpression(range), TypeNode.createIdentifierExpression("__aspectStrictEquals", range), range),
|
|
158
164
|
], range), TypeNode.createBlockStatement([
|
|
159
|
-
TypeNode.createIfStatement(TypeNode.createUnaryPrefixExpression(95 /* Token.
|
|
165
|
+
TypeNode.createIfStatement(TypeNode.createUnaryPrefixExpression(95 /* Token.Exclamation */, createSuperCallExpression(nameHashes, range), range), TypeNode.createReturnStatement(TypeNode.createFalseExpression(range), range), null, range),
|
|
160
166
|
], range), null, range);
|
|
161
167
|
return ifStatement;
|
|
162
168
|
}
|
|
@@ -175,7 +181,7 @@ function createSuperCallExpression(hashValues, range) {
|
|
|
175
181
|
TypeNode.createCallExpression(TypeNode.createPropertyAccessExpression(TypeNode.createIdentifierExpression("StaticArray", range), TypeNode.createIdentifierExpression("concat", range), range), null, [
|
|
176
182
|
TypeNode.createIdentifierExpression("ignore", range),
|
|
177
183
|
// [...] as StaticArray<i64>
|
|
178
|
-
TypeNode.createAssertionExpression(1 /* AssertionKind.
|
|
184
|
+
TypeNode.createAssertionExpression(1 /* AssertionKind.As */, TypeNode.createArrayLiteralExpression(hashValues.map((e) => TypeNode.createIntegerLiteralExpression(f64_as_i64(e), range)), range), TypeNode.createNamedType(TypeNode.createSimpleTypeName("StaticArray", range), [TypeNode.createNamedType(TypeNode.createSimpleTypeName("i64", range), null, false, range)], false, range), range),
|
|
179
185
|
], range),
|
|
180
186
|
], range);
|
|
181
187
|
}
|
package/lib/index.js
CHANGED
|
@@ -12,9 +12,7 @@ export default class AspectTransform extends Transform {
|
|
|
12
12
|
// @ts-ignore
|
|
13
13
|
afterParse(parser) {
|
|
14
14
|
// For backwards compatibility
|
|
15
|
-
let sources = parser.program
|
|
16
|
-
? parser.program.sources
|
|
17
|
-
: parser.sources;
|
|
15
|
+
let sources = parser.program ? parser.program.sources : parser.sources;
|
|
18
16
|
// for each program source
|
|
19
17
|
for (const source of sources) {
|
|
20
18
|
traverseStatements(source.statements);
|
|
@@ -25,13 +23,13 @@ function traverseStatements(statements) {
|
|
|
25
23
|
// for each statement in the source
|
|
26
24
|
for (const statement of statements) {
|
|
27
25
|
// find each class declaration
|
|
28
|
-
if (statement.kind === 51 /* NodeKind.
|
|
26
|
+
if (statement.kind === 51 /* NodeKind.ClassDeclaration */) {
|
|
29
27
|
// cast and create a strictEquals function
|
|
30
28
|
const classDeclaration = statement;
|
|
31
29
|
classDeclaration.members.push(createStrictEqualsMember(classDeclaration));
|
|
32
30
|
classDeclaration.members.push(createAddReflectedValueKeyValuePairsMember(classDeclaration));
|
|
33
31
|
}
|
|
34
|
-
else if (statement.kind === 59 /* NodeKind.
|
|
32
|
+
else if (statement.kind === 59 /* NodeKind.NamespaceDeclaration */) {
|
|
35
33
|
const namespaceDeclaration = statement;
|
|
36
34
|
traverseStatements(namespaceDeclaration.members);
|
|
37
35
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@as-pect/transform",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "The transform used by the as-pect core and assembly packages to enable strict equality.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"author": "Joshua Tenner <tenner.joshua@gmail.com>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"assemblyscript": "^0.
|
|
13
|
+
"assemblyscript": "^0.24.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"typescript": "^4.8.
|
|
16
|
+
"typescript": "^4.8.4"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"lib/",
|