From ba106b382bed0c7f7f9d9ca639abf192fbcecb69 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 13:05:50 -0600 Subject: [PATCH 01/13] initial fix --- src/diagnosticMessages.generated.ts | 8 + src/diagnosticMessages.json | 4 + src/program.ts | 7 - src/resolver.ts | 61 +- tests/compiler/duplicate-field-errors.json | 10 + tests/compiler/duplicate-field-errors.ts | 26 + tests/compiler/duplicate-fields.json | 4 + tests/compiler/duplicate-fields.optimized.wat | 2122 +++++++++++++++++ tests/compiler/duplicate-fields.ts | 54 + tests/compiler/duplicate-fields.untouched.wat | 0 10 files changed, 2279 insertions(+), 17 deletions(-) create mode 100644 tests/compiler/duplicate-field-errors.json create mode 100644 tests/compiler/duplicate-field-errors.ts create mode 100644 tests/compiler/duplicate-fields.json create mode 100644 tests/compiler/duplicate-fields.optimized.wat create mode 100644 tests/compiler/duplicate-fields.ts create mode 100644 tests/compiler/duplicate-fields.untouched.wat diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 2db65faca4..b52aeee707 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -123,6 +123,7 @@ export enum DiagnosticCode { Generic_type_0_requires_1_type_argument_s = 2314, Type_0_is_not_generic = 2315, Type_0_is_not_assignable_to_type_1 = 2322, + Property_0_is_private_in_type_1_but_not_in_type_2 = 2325, Index_signature_is_missing_in_type_0 = 2329, _this_cannot_be_referenced_in_current_location = 2332, _this_cannot_be_referenced_in_constructor_arguments = 2333, @@ -148,8 +149,10 @@ export enum DiagnosticCode { Duplicate_function_implementation = 2393, This_overload_signature_is_not_compatible_with_its_implementation_signature = 2394, Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local = 2395, + Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2 = 2416, A_class_can_only_implement_an_interface = 2422, A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged = 2434, + Types_have_separate_declarations_of_a_private_property_0 = 2442, Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses = 2445, Variable_0_used_before_its_declaration = 2448, Cannot_redeclare_block_scoped_variable_0 = 2451, @@ -170,6 +173,7 @@ export enum DiagnosticCode { Expected_0_type_arguments_but_got_1 = 2558, Property_0_has_no_initializer_and_is_not_assigned_in_the_constructor_before_this_is_used_or_returned = 2564, Property_0_is_used_before_being_assigned = 2565, + Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration = 2612, A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums = 2651, Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration = 2673, Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration = 2674, @@ -307,6 +311,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2314: return "Generic type '{0}' requires {1} type argument(s)."; case 2315: return "Type '{0}' is not generic."; case 2322: return "Type '{0}' is not assignable to type '{1}'."; + case 2325: return "Property '{0}' is private in type '{1}' but not in type '{2}'."; case 2329: return "Index signature is missing in type '{0}'."; case 2332: return "'this' cannot be referenced in current location."; case 2333: return "'this' cannot be referenced in constructor arguments."; @@ -332,8 +337,10 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2393: return "Duplicate function implementation."; case 2394: return "This overload signature is not compatible with its implementation signature."; case 2395: return "Individual declarations in merged declaration '{0}' must be all exported or all local."; + case 2416: return "Property '{0}' in type '{1}' is not assignable to the same property in base type '{2}'."; case 2422: return "A class can only implement an interface."; case 2434: return "A namespace declaration cannot be located prior to a class or function with which it is merged."; + case 2442: return "Types have separate declarations of a private property '{0}'."; case 2445: return "Property '{0}' is protected and only accessible within class '{1}' and its subclasses."; case 2448: return "Variable '{0}' used before its declaration."; case 2451: return "Cannot redeclare block-scoped variable '{0}'"; @@ -354,6 +361,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2558: return "Expected {0} type arguments, but got {1}."; case 2564: return "Property '{0}' has no initializer and is not assigned in the constructor before 'this' is used or returned."; case 2565: return "Property '{0}' is used before being assigned."; + case 2612: return "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration."; case 2651: return "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums."; case 2673: return "Constructor of class '{0}' is private and only accessible within the class declaration."; case 2674: return "Constructor of class '{0}' is protected and only accessible within the class declaration."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 0b6d18ab7b..9952871646 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -121,6 +121,7 @@ "Generic type '{0}' requires {1} type argument(s).": 2314, "Type '{0}' is not generic.": 2315, "Type '{0}' is not assignable to type '{1}'.": 2322, + "Property '{0}' is private in type '{1}' but not in type '{2}'.": 2325, "Index signature is missing in type '{0}'.": 2329, "'this' cannot be referenced in current location.": 2332, "'this' cannot be referenced in constructor arguments.": 2333, @@ -146,8 +147,10 @@ "Duplicate function implementation.": 2393, "This overload signature is not compatible with its implementation signature.": 2394, "Individual declarations in merged declaration '{0}' must be all exported or all local.": 2395, + "Property '{0}' in type '{1}' is not assignable to the same property in base type '{2}'.": 2416, "A class can only implement an interface.": 2422, "A namespace declaration cannot be located prior to a class or function with which it is merged.": 2434, + "Types have separate declarations of a private property '{0}'.": 2442, "Property '{0}' is protected and only accessible within class '{1}' and its subclasses.": 2445, "Variable '{0}' used before its declaration.": 2448, "Cannot redeclare block-scoped variable '{0}'" : 2451, @@ -168,6 +171,7 @@ "Expected {0} type arguments, but got {1}.": 2558, "Property '{0}' has no initializer and is not assigned in the constructor before 'this' is used or returned.": 2564, "Property '{0}' is used before being assigned.": 2565, + "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.": 2612, "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": 2651, "Constructor of class '{0}' is private and only accessible within the class declaration.": 2673, "Constructor of class '{0}' is protected and only accessible within the class declaration.": 2674, diff --git a/src/program.ts b/src/program.ts index 8df389b4b4..e1faf7596f 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1513,13 +1513,6 @@ export class Program extends DiagnosticEmitter { } } } - } else { - this.errorRelated( - DiagnosticCode.Duplicate_identifier_0, - thisMember.identifierNode.range, - baseMember.identifierNode.range, - baseMember.identifierNode.text - ); } } } diff --git a/src/resolver.ts b/src/resolver.ts index dd79ab78f3..1e4ddc2552 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3092,18 +3092,43 @@ export class Resolver extends DiagnosticEmitter { let fieldPrototype = member; let fieldTypeNode = fieldPrototype.typeNode; let fieldType: Type | null = null; - // TODO: handle duplicate non-private fields specifically? - if (!fieldTypeNode) { - if (base) { - let baseMembers = base.members; - if (baseMembers !== null && baseMembers.has(fieldPrototype.name)) { - let baseField = assert(baseMembers.get(fieldPrototype.name)); - if (!baseField.is(CommonFlags.PRIVATE)) { - assert(baseField.kind == ElementKind.FIELD); - fieldType = (baseField).type; - } + let existingField: Field | null = null; + if (base) { + let baseMembers = base.members; + if (baseMembers !== null && baseMembers.has(fieldPrototype.name)) { + let baseField = assert(baseMembers.get(fieldPrototype.name)); + assert(baseField.kind == ElementKind.FIELD); + existingField = baseField; + + // visibility checks + let thisFieldIsPublic = fieldPrototype.isPublic; + let existingFieldIsPublic = existingField.isPublic; + + if (thisFieldIsPublic && !existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, base.internalName, instance.internalName + ); + } else if (!thisFieldIsPublic && existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, instance.internalName, base.internalName + ); + } else if (!thisFieldIsPublic && !existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Types_have_separate_declarations_of_a_private_property_0, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name + ); } } + } + if (!fieldTypeNode) { + if (existingField !== null && !existingField.is(CommonFlags.PRIVATE)) { + fieldType = existingField.type; + } if (!fieldType) { if (reportMode == ReportMode.REPORT) { this.error( @@ -3130,6 +3155,22 @@ export class Resolver extends DiagnosticEmitter { } } if (!fieldType) break; // did report above + if (existingField !== null) { + // assignability checks + if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null && !fieldPrototype.is(CommonFlags.DECLARE)) { + this.errorRelated( + DiagnosticCode.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, assert(base).internalName + ); + } else if (!fieldType.isStrictlyAssignableTo(existingField.type)) { + this.errorRelated( + DiagnosticCode.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, instance.internalName, assert(base).internalName + ); + } + } let fieldInstance = new Field(fieldPrototype, instance, fieldType); assert(isPowerOf2(fieldType.byteSize)); let mask = fieldType.byteSize - 1; diff --git a/tests/compiler/duplicate-field-errors.json b/tests/compiler/duplicate-field-errors.json new file mode 100644 index 0000000000..d0afa77c37 --- /dev/null +++ b/tests/compiler/duplicate-field-errors.json @@ -0,0 +1,10 @@ +{ + "asc_flags": [ + ], + "stderr": [ + "TS2325: Property 'foo' is private in type 'duplicate-field-errors/A' but not in type 'duplicate-field-errors/B'.", + "TS2325: Property 'bar' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", + "TS2442: Types have separate declarations of a private property 'baz'.", + "TS2416: Property 'raz' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'." + ] +} diff --git a/tests/compiler/duplicate-field-errors.ts b/tests/compiler/duplicate-field-errors.ts new file mode 100644 index 0000000000..19f9379d9d --- /dev/null +++ b/tests/compiler/duplicate-field-errors.ts @@ -0,0 +1,26 @@ +class A { + private a: i32; + public b: i32; + private c: i32; + public d: i64; + public e: i32; + constructor(a: i32, b: i32, c: i32, d: i64, e: i32) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + this.e = e; + } +} + +export class B extends A { + public a: i32; + private b: i32; + private c: i32; + public d: i32; + public e: i32; + constructor(a: i32, b: i32, c: i32, d: i32, e: i32) { + super(a, b, c, d, e); + } +} + diff --git a/tests/compiler/duplicate-fields.json b/tests/compiler/duplicate-fields.json new file mode 100644 index 0000000000..1bdd02b1be --- /dev/null +++ b/tests/compiler/duplicate-fields.json @@ -0,0 +1,4 @@ +{ + "asc_flags": [ + ] +} diff --git a/tests/compiler/duplicate-fields.optimized.wat b/tests/compiler/duplicate-fields.optimized.wat new file mode 100644 index 0000000000..3793b5b337 --- /dev/null +++ b/tests/compiler/duplicate-fields.optimized.wat @@ -0,0 +1,2122 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (global $~lib/rt/itcms/total (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/threshold (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/state (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/visitCount (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/pinSpace (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/iter (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/toSpace (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/white (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/fromSpace (mut i32) (i32.const 0)) + (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) + (global $duplicate-fields/foo (mut i32) (i32.const 0)) + (global $duplicate-fields/baz (mut i32) (i32.const 0)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 17964)) + (memory $0 1) + (data (i32.const 1036) "<") + (data (i32.const 1048) "\01\00\00\00(\00\00\00A\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e") + (data (i32.const 1100) "<") + (data (i32.const 1112) "\01\00\00\00 \00\00\00~\00l\00i\00b\00/\00r\00t\00/\00i\00t\00c\00m\00s\00.\00t\00s") + (data (i32.const 1228) "<") + (data (i32.const 1240) "\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e") + (data (i32.const 1292) ",") + (data (i32.const 1304) "\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s") + (data (i32.const 1372) "<") + (data (i32.const 1384) "\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s") + (data (i32.const 1436) "<") + (data (i32.const 1448) "\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s") + (data (i32.const 1504) "\t\00\00\00 \00\00\00\00\00\00\00 ") + (data (i32.const 1532) " \00\00\00\04\00\00\00 ") + (data (i32.const 1552) "\06") + (data (i32.const 1564) " \00\00\00\00\00\00\00 \00\00\00\07") + (export "memory" (memory $0)) + (start $~start) + (func $~lib/rt/itcms/visitRoots + (local $0 i32) + (local $1 i32) + global.get $duplicate-fields/foo + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + global.get $duplicate-fields/baz + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + i32.const 1248 + call $~lib/rt/itcms/__visit + i32.const 1056 + call $~lib/rt/itcms/__visit + global.get $~lib/rt/itcms/pinSpace + local.tee $1 + i32.load offset=4 + i32.const -4 + i32.and + local.set $0 + loop $while-continue|0 + local.get $0 + local.get $1 + i32.ne + if + local.get $0 + i32.load offset=4 + i32.const 3 + i32.and + i32.const 3 + i32.ne + if + i32.const 0 + i32.const 1120 + i32.const 159 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.const 20 + i32.add + call $~lib/rt/__visit_members + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + local.set $0 + br $while-continue|0 + end + end + ) + (func $~lib/rt/itcms/Object#makeGray (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + global.get $~lib/rt/itcms/iter + local.get $0 + i32.eq + if + local.get $0 + i32.load offset=8 + local.tee $1 + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 147 + i32.const 30 + call $~lib/builtins/abort + unreachable + end + local.get $1 + global.set $~lib/rt/itcms/iter + end + block $__inlined_func$~lib/rt/itcms/Object#unlink + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + local.tee $1 + i32.eqz + if + i32.const 0 + local.get $0 + i32.const 17964 + i32.lt_u + local.get $0 + i32.load offset=8 + select + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 127 + i32.const 18 + call $~lib/builtins/abort + unreachable + end + br $__inlined_func$~lib/rt/itcms/Object#unlink + end + local.get $0 + i32.load offset=8 + local.tee $2 + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 131 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $1 + local.get $2 + i32.store offset=8 + local.get $2 + local.get $2 + i32.load offset=4 + i32.const 3 + i32.and + local.get $1 + i32.or + i32.store offset=4 + end + global.get $~lib/rt/itcms/toSpace + local.set $2 + local.get $0 + i32.load offset=12 + local.tee $1 + i32.const 1 + i32.le_u + if (result i32) + i32.const 1 + else + i32.const 1504 + i32.load + local.get $1 + i32.lt_u + if + i32.const 1248 + i32.const 1312 + i32.const 22 + i32.const 28 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 3 + i32.shl + i32.const 1508 + i32.add + i32.load + i32.const 32 + i32.and + end + local.set $3 + local.get $2 + i32.load offset=8 + local.set $1 + local.get $0 + local.get $2 + global.get $~lib/rt/itcms/white + i32.eqz + i32.const 2 + local.get $3 + select + i32.or + i32.store offset=4 + local.get $0 + local.get $1 + i32.store offset=8 + local.get $1 + local.get $1 + i32.load offset=4 + i32.const 3 + i32.and + local.get $0 + i32.or + i32.store offset=4 + local.get $2 + local.get $0 + i32.store offset=8 + ) + (func $~lib/rt/itcms/__visit (param $0 i32) + local.get $0 + i32.eqz + if + return + end + global.get $~lib/rt/itcms/white + local.get $0 + i32.const 20 + i32.sub + local.tee $0 + i32.load offset=4 + i32.const 3 + i32.and + i32.eq + if + local.get $0 + call $~lib/rt/itcms/Object#makeGray + global.get $~lib/rt/itcms/visitCount + i32.const 1 + i32.add + global.set $~lib/rt/itcms/visitCount + end + ) + (func $~lib/rt/tlsf/removeBlock (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + local.get $1 + i32.load + local.tee $2 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 268 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const -4 + i32.and + local.tee $2 + i32.const 12 + i32.lt_u + if + i32.const 0 + i32.const 1392 + i32.const 270 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 256 + i32.lt_u + if (result i32) + local.get $2 + i32.const 4 + i32.shr_u + else + i32.const 31 + local.get $2 + i32.const 1073741820 + local.get $2 + i32.const 1073741820 + i32.lt_u + select + local.tee $2 + i32.clz + i32.sub + local.tee $4 + i32.const 7 + i32.sub + local.set $3 + local.get $2 + local.get $4 + i32.const 4 + i32.sub + i32.shr_u + i32.const 16 + i32.xor + end + local.tee $2 + i32.const 16 + i32.lt_u + i32.const 0 + local.get $3 + i32.const 23 + i32.lt_u + select + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 284 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load offset=8 + local.set $5 + local.get $1 + i32.load offset=4 + local.tee $4 + if + local.get $4 + local.get $5 + i32.store offset=8 + end + local.get $5 + if + local.get $5 + local.get $4 + i32.store offset=4 + end + local.get $2 + local.get $3 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + local.get $0 + i32.add + i32.load offset=96 + local.get $1 + i32.eq + if + local.get $2 + local.get $3 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + local.get $0 + i32.add + local.get $5 + i32.store offset=96 + local.get $5 + i32.eqz + if + local.get $3 + i32.const 2 + i32.shl + local.get $0 + i32.add + local.tee $1 + i32.load offset=4 + i32.const -2 + local.get $2 + i32.rotl + i32.and + local.set $2 + local.get $1 + local.get $2 + i32.store offset=4 + local.get $2 + i32.eqz + if + local.get $0 + local.get $0 + i32.load + i32.const -2 + local.get $3 + i32.rotl + i32.and + i32.store + end + end + end + ) + (func $~lib/rt/tlsf/insertBlock (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + local.get $1 + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 201 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load + local.tee $3 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 203 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 4 + i32.add + local.get $1 + i32.load + i32.const -4 + i32.and + i32.add + local.tee $4 + i32.load + local.tee $2 + i32.const 1 + i32.and + if + local.get $0 + local.get $4 + call $~lib/rt/tlsf/removeBlock + local.get $1 + local.get $3 + i32.const 4 + i32.add + local.get $2 + i32.const -4 + i32.and + i32.add + local.tee $3 + i32.store + local.get $1 + i32.const 4 + i32.add + local.get $1 + i32.load + i32.const -4 + i32.and + i32.add + local.tee $4 + i32.load + local.set $2 + end + local.get $3 + i32.const 2 + i32.and + if + local.get $1 + i32.const 4 + i32.sub + i32.load + local.tee $1 + i32.load + local.tee $6 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 221 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $1 + call $~lib/rt/tlsf/removeBlock + local.get $1 + local.get $6 + i32.const 4 + i32.add + local.get $3 + i32.const -4 + i32.and + i32.add + local.tee $3 + i32.store + end + local.get $4 + local.get $2 + i32.const 2 + i32.or + i32.store + local.get $3 + i32.const -4 + i32.and + local.tee $2 + i32.const 12 + i32.lt_u + if + i32.const 0 + i32.const 1392 + i32.const 233 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $2 + local.get $1 + i32.const 4 + i32.add + i32.add + local.get $4 + i32.ne + if + i32.const 0 + i32.const 1392 + i32.const 234 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $4 + i32.const 4 + i32.sub + local.get $1 + i32.store + local.get $2 + i32.const 256 + i32.lt_u + if (result i32) + local.get $2 + i32.const 4 + i32.shr_u + else + i32.const 31 + local.get $2 + i32.const 1073741820 + local.get $2 + i32.const 1073741820 + i32.lt_u + select + local.tee $2 + i32.clz + i32.sub + local.tee $3 + i32.const 7 + i32.sub + local.set $5 + local.get $2 + local.get $3 + i32.const 4 + i32.sub + i32.shr_u + i32.const 16 + i32.xor + end + local.tee $2 + i32.const 16 + i32.lt_u + i32.const 0 + local.get $5 + i32.const 23 + i32.lt_u + select + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 251 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $2 + local.get $5 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + local.get $0 + i32.add + i32.load offset=96 + local.set $3 + local.get $1 + i32.const 0 + i32.store offset=4 + local.get $1 + local.get $3 + i32.store offset=8 + local.get $3 + if + local.get $3 + local.get $1 + i32.store offset=4 + end + local.get $2 + local.get $5 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + local.get $0 + i32.add + local.get $1 + i32.store offset=96 + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $5 + i32.shl + i32.or + i32.store + local.get $5 + i32.const 2 + i32.shl + local.get $0 + i32.add + local.tee $0 + local.get $0 + i32.load offset=4 + i32.const 1 + local.get $2 + i32.shl + i32.or + i32.store offset=4 + ) + (func $~lib/rt/tlsf/addMemory (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + local.get $1 + local.get $2 + i32.gt_u + if + i32.const 0 + i32.const 1392 + i32.const 377 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 19 + i32.add + i32.const -16 + i32.and + i32.const 4 + i32.sub + local.set $1 + local.get $0 + i32.load offset=1568 + local.tee $4 + if + local.get $1 + local.get $4 + i32.const 4 + i32.add + i32.lt_u + if + i32.const 0 + i32.const 1392 + i32.const 384 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $4 + local.get $1 + i32.const 16 + i32.sub + i32.eq + if + local.get $4 + i32.load + local.set $3 + local.get $1 + i32.const 16 + i32.sub + local.set $1 + end + else + local.get $1 + local.get $0 + i32.const 1572 + i32.add + i32.lt_u + if + i32.const 0 + i32.const 1392 + i32.const 397 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + end + local.get $2 + i32.const -16 + i32.and + local.get $1 + i32.sub + local.tee $2 + i32.const 20 + i32.lt_u + if + return + end + local.get $1 + local.get $3 + i32.const 2 + i32.and + local.get $2 + i32.const 8 + i32.sub + local.tee $2 + i32.const 1 + i32.or + i32.or + i32.store + local.get $1 + i32.const 0 + i32.store offset=4 + local.get $1 + i32.const 0 + i32.store offset=8 + local.get $2 + local.get $1 + i32.const 4 + i32.add + i32.add + local.tee $2 + i32.const 2 + i32.store + local.get $0 + local.get $2 + i32.store offset=1568 + local.get $0 + local.get $1 + call $~lib/rt/tlsf/insertBlock + ) + (func $~lib/rt/tlsf/initialize + (local $0 i32) + (local $1 i32) + memory.size + local.tee $1 + i32.const 1 + i32.lt_s + if (result i32) + i32.const 1 + local.get $1 + i32.sub + memory.grow + i32.const 0 + i32.lt_s + else + i32.const 0 + end + if + unreachable + end + i32.const 17968 + i32.const 0 + i32.store + i32.const 19536 + i32.const 0 + i32.store + loop $for-loop|0 + local.get $0 + i32.const 23 + i32.lt_u + if + local.get $0 + i32.const 2 + i32.shl + i32.const 17968 + i32.add + i32.const 0 + i32.store offset=4 + i32.const 0 + local.set $1 + loop $for-loop|1 + local.get $1 + i32.const 16 + i32.lt_u + if + local.get $1 + local.get $0 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.const 17968 + i32.add + i32.const 0 + i32.store offset=96 + local.get $1 + i32.const 1 + i32.add + local.set $1 + br $for-loop|1 + end + end + local.get $0 + i32.const 1 + i32.add + local.set $0 + br $for-loop|0 + end + end + i32.const 17968 + i32.const 19540 + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + i32.const 17968 + global.set $~lib/rt/tlsf/ROOT + ) + (func $~lib/rt/itcms/step (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + block $break|0 + block $case2|0 + block $case1|0 + block $case0|0 + global.get $~lib/rt/itcms/state + br_table $case0|0 $case1|0 $case2|0 $break|0 + end + i32.const 1 + global.set $~lib/rt/itcms/state + i32.const 0 + global.set $~lib/rt/itcms/visitCount + call $~lib/rt/itcms/visitRoots + global.get $~lib/rt/itcms/toSpace + global.set $~lib/rt/itcms/iter + global.get $~lib/rt/itcms/visitCount + return + end + global.get $~lib/rt/itcms/white + i32.eqz + local.set $1 + global.get $~lib/rt/itcms/iter + i32.load offset=4 + i32.const -4 + i32.and + local.set $0 + loop $while-continue|1 + global.get $~lib/rt/itcms/toSpace + local.get $0 + i32.ne + if + local.get $0 + global.set $~lib/rt/itcms/iter + local.get $0 + i32.load offset=4 + i32.const 3 + i32.and + local.get $1 + i32.ne + if + local.get $0 + local.get $1 + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + i32.or + i32.store offset=4 + i32.const 0 + global.set $~lib/rt/itcms/visitCount + local.get $0 + i32.const 20 + i32.add + call $~lib/rt/__visit_members + global.get $~lib/rt/itcms/visitCount + return + end + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + local.set $0 + br $while-continue|1 + end + end + i32.const 0 + global.set $~lib/rt/itcms/visitCount + call $~lib/rt/itcms/visitRoots + global.get $~lib/rt/itcms/toSpace + global.get $~lib/rt/itcms/iter + i32.load offset=4 + i32.const -4 + i32.and + i32.eq + if + global.get $~lib/memory/__stack_pointer + local.set $0 + loop $while-continue|0 + local.get $0 + i32.const 17964 + i32.lt_u + if + local.get $0 + i32.load + call $~lib/rt/itcms/__visit + local.get $0 + i32.const 4 + i32.add + local.set $0 + br $while-continue|0 + end + end + global.get $~lib/rt/itcms/iter + i32.load offset=4 + i32.const -4 + i32.and + local.set $0 + loop $while-continue|2 + global.get $~lib/rt/itcms/toSpace + local.get $0 + i32.ne + if + local.get $0 + i32.load offset=4 + i32.const 3 + i32.and + local.get $1 + i32.ne + if + local.get $0 + local.get $1 + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + i32.or + i32.store offset=4 + local.get $0 + i32.const 20 + i32.add + call $~lib/rt/__visit_members + end + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + local.set $0 + br $while-continue|2 + end + end + global.get $~lib/rt/itcms/fromSpace + local.set $0 + global.get $~lib/rt/itcms/toSpace + global.set $~lib/rt/itcms/fromSpace + local.get $0 + global.set $~lib/rt/itcms/toSpace + local.get $1 + global.set $~lib/rt/itcms/white + local.get $0 + i32.load offset=4 + i32.const -4 + i32.and + global.set $~lib/rt/itcms/iter + i32.const 2 + global.set $~lib/rt/itcms/state + end + global.get $~lib/rt/itcms/visitCount + return + end + global.get $~lib/rt/itcms/iter + local.tee $0 + global.get $~lib/rt/itcms/toSpace + i32.ne + if + local.get $0 + i32.load offset=4 + local.tee $1 + i32.const -4 + i32.and + global.set $~lib/rt/itcms/iter + global.get $~lib/rt/itcms/white + i32.eqz + local.get $1 + i32.const 3 + i32.and + i32.ne + if + i32.const 0 + i32.const 1120 + i32.const 228 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.const 17964 + i32.lt_u + if + local.get $0 + i32.const 0 + i32.store offset=4 + local.get $0 + i32.const 0 + i32.store offset=8 + else + global.get $~lib/rt/itcms/total + local.get $0 + i32.load + i32.const -4 + i32.and + i32.const 4 + i32.add + i32.sub + global.set $~lib/rt/itcms/total + local.get $0 + i32.const 4 + i32.add + local.tee $1 + i32.const 17964 + i32.ge_u + if + global.get $~lib/rt/tlsf/ROOT + i32.eqz + if + call $~lib/rt/tlsf/initialize + end + global.get $~lib/rt/tlsf/ROOT + local.get $1 + i32.const 4 + i32.sub + local.set $0 + local.get $1 + i32.const 15 + i32.and + i32.const 1 + local.get $1 + select + if (result i32) + i32.const 1 + else + local.get $0 + i32.load + i32.const 1 + i32.and + end + if + i32.const 0 + i32.const 1392 + i32.const 559 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $0 + i32.load + i32.const 1 + i32.or + i32.store + local.get $0 + call $~lib/rt/tlsf/insertBlock + end + end + i32.const 10 + return + end + global.get $~lib/rt/itcms/toSpace + local.tee $0 + local.get $0 + i32.store offset=4 + local.get $0 + local.get $0 + i32.store offset=8 + i32.const 0 + global.set $~lib/rt/itcms/state + end + i32.const 0 + ) + (func $~lib/rt/tlsf/searchBlock (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + local.get $1 + i32.const 256 + i32.lt_u + if + local.get $1 + i32.const 4 + i32.shr_u + local.set $1 + else + local.get $1 + i32.const 536870910 + i32.lt_u + if + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + local.get $1 + i32.add + i32.const 1 + i32.sub + local.set $1 + end + local.get $1 + i32.const 31 + local.get $1 + i32.clz + i32.sub + local.tee $2 + i32.const 4 + i32.sub + i32.shr_u + i32.const 16 + i32.xor + local.set $1 + local.get $2 + i32.const 7 + i32.sub + local.set $2 + end + local.get $1 + i32.const 16 + i32.lt_u + i32.const 0 + local.get $2 + i32.const 23 + i32.lt_u + select + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 330 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 2 + i32.shl + local.get $0 + i32.add + i32.load offset=4 + i32.const -1 + local.get $1 + i32.shl + i32.and + local.tee $1 + if (result i32) + local.get $1 + i32.ctz + local.get $2 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + local.get $0 + i32.add + i32.load offset=96 + else + local.get $0 + i32.load + i32.const -1 + local.get $2 + i32.const 1 + i32.add + i32.shl + i32.and + local.tee $1 + if (result i32) + local.get $1 + i32.ctz + local.tee $1 + i32.const 2 + i32.shl + local.get $0 + i32.add + i32.load offset=4 + local.tee $2 + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 343 + i32.const 18 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.ctz + local.get $1 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + local.get $0 + i32.add + i32.load offset=96 + else + i32.const 0 + end + end + ) + (func $~lib/rt/itcms/__new (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + local.get $0 + i32.const 1073741804 + i32.ge_u + if + i32.const 1056 + i32.const 1120 + i32.const 260 + i32.const 31 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/rt/itcms/total + global.get $~lib/rt/itcms/threshold + i32.ge_u + if + block $__inlined_func$~lib/rt/itcms/interrupt + i32.const 2048 + local.set $2 + loop $do-loop|0 + local.get $2 + call $~lib/rt/itcms/step + i32.sub + local.set $2 + global.get $~lib/rt/itcms/state + i32.eqz + if + global.get $~lib/rt/itcms/total + i64.extend_i32_u + i64.const 200 + i64.mul + i64.const 100 + i64.div_u + i32.wrap_i64 + i32.const 1024 + i32.add + global.set $~lib/rt/itcms/threshold + br $__inlined_func$~lib/rt/itcms/interrupt + end + local.get $2 + i32.const 0 + i32.gt_s + br_if $do-loop|0 + end + global.get $~lib/rt/itcms/total + local.tee $2 + local.get $2 + global.get $~lib/rt/itcms/threshold + i32.sub + i32.const 1024 + i32.lt_u + i32.const 10 + i32.shl + i32.add + global.set $~lib/rt/itcms/threshold + end + end + global.get $~lib/rt/tlsf/ROOT + i32.eqz + if + call $~lib/rt/tlsf/initialize + end + global.get $~lib/rt/tlsf/ROOT + local.set $3 + local.get $0 + i32.const 16 + i32.add + local.tee $2 + i32.const 1073741820 + i32.gt_u + if + i32.const 1056 + i32.const 1392 + i32.const 458 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + local.get $3 + local.get $2 + i32.const 12 + i32.le_u + if (result i32) + i32.const 12 + else + local.get $2 + i32.const 19 + i32.add + i32.const -16 + i32.and + i32.const 4 + i32.sub + end + local.tee $5 + call $~lib/rt/tlsf/searchBlock + local.tee $2 + i32.eqz + if + memory.size + local.tee $2 + local.get $5 + i32.const 536870910 + i32.lt_u + if (result i32) + i32.const 1 + i32.const 27 + local.get $5 + i32.clz + i32.sub + i32.shl + i32.const 1 + i32.sub + local.get $5 + i32.add + else + local.get $5 + end + i32.const 4 + local.get $3 + i32.load offset=1568 + local.get $2 + i32.const 16 + i32.shl + i32.const 4 + i32.sub + i32.ne + i32.shl + i32.add + i32.const 65535 + i32.add + i32.const -65536 + i32.and + i32.const 16 + i32.shr_u + local.tee $4 + local.get $2 + local.get $4 + i32.gt_s + select + memory.grow + i32.const 0 + i32.lt_s + if + local.get $4 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + local.get $3 + local.get $2 + i32.const 16 + i32.shl + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + local.get $3 + local.get $5 + call $~lib/rt/tlsf/searchBlock + local.tee $2 + i32.eqz + if + i32.const 0 + i32.const 1392 + i32.const 496 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + end + local.get $2 + i32.load + i32.const -4 + i32.and + local.get $5 + i32.lt_u + if + i32.const 0 + i32.const 1392 + i32.const 498 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $3 + local.get $2 + call $~lib/rt/tlsf/removeBlock + local.get $2 + i32.load + local.set $4 + local.get $5 + i32.const 4 + i32.add + i32.const 15 + i32.and + if + i32.const 0 + i32.const 1392 + i32.const 357 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $4 + i32.const -4 + i32.and + local.get $5 + i32.sub + local.tee $6 + i32.const 16 + i32.ge_u + if + local.get $2 + local.get $4 + i32.const 2 + i32.and + local.get $5 + i32.or + i32.store + local.get $5 + local.get $2 + i32.const 4 + i32.add + i32.add + local.tee $4 + local.get $6 + i32.const 4 + i32.sub + i32.const 1 + i32.or + i32.store + local.get $3 + local.get $4 + call $~lib/rt/tlsf/insertBlock + else + local.get $2 + local.get $4 + i32.const -2 + i32.and + i32.store + local.get $2 + i32.const 4 + i32.add + local.get $2 + i32.load + i32.const -4 + i32.and + i32.add + local.tee $3 + local.get $3 + i32.load + i32.const -3 + i32.and + i32.store + end + local.get $2 + local.get $1 + i32.store offset=12 + local.get $2 + local.get $0 + i32.store offset=16 + global.get $~lib/rt/itcms/fromSpace + local.tee $1 + i32.load offset=8 + local.set $3 + local.get $2 + global.get $~lib/rt/itcms/white + local.get $1 + i32.or + i32.store offset=4 + local.get $2 + local.get $3 + i32.store offset=8 + local.get $3 + local.get $3 + i32.load offset=4 + i32.const 3 + i32.and + local.get $2 + i32.or + i32.store offset=4 + local.get $1 + local.get $2 + i32.store offset=8 + global.get $~lib/rt/itcms/total + local.get $2 + i32.load + i32.const -4 + i32.and + i32.const 4 + i32.add + i32.add + global.set $~lib/rt/itcms/total + local.get $2 + i32.const 20 + i32.add + local.tee $2 + local.set $1 + block $~lib/util/memory/memset|inlined.0 + local.get $0 + i32.eqz + br_if $~lib/util/memory/memset|inlined.0 + local.get $1 + i32.const 0 + i32.store8 + local.get $0 + local.get $1 + i32.add + local.tee $3 + i32.const 1 + i32.sub + i32.const 0 + i32.store8 + local.get $0 + i32.const 2 + i32.le_u + br_if $~lib/util/memory/memset|inlined.0 + local.get $1 + i32.const 0 + i32.store8 offset=1 + local.get $1 + i32.const 0 + i32.store8 offset=2 + local.get $3 + i32.const 2 + i32.sub + i32.const 0 + i32.store8 + local.get $3 + i32.const 3 + i32.sub + i32.const 0 + i32.store8 + local.get $0 + i32.const 6 + i32.le_u + br_if $~lib/util/memory/memset|inlined.0 + local.get $1 + i32.const 0 + i32.store8 offset=3 + local.get $3 + i32.const 4 + i32.sub + i32.const 0 + i32.store8 + local.get $0 + i32.const 8 + i32.le_u + br_if $~lib/util/memory/memset|inlined.0 + local.get $1 + i32.const 0 + local.get $1 + i32.sub + i32.const 3 + i32.and + local.tee $3 + i32.add + local.tee $1 + i32.const 0 + i32.store + local.get $1 + local.get $0 + local.get $3 + i32.sub + i32.const -4 + i32.and + local.tee $0 + i32.add + local.tee $3 + i32.const 4 + i32.sub + i32.const 0 + i32.store + local.get $0 + i32.const 8 + i32.le_u + br_if $~lib/util/memory/memset|inlined.0 + local.get $1 + i32.const 0 + i32.store offset=4 + local.get $1 + i32.const 0 + i32.store offset=8 + local.get $3 + i32.const 12 + i32.sub + i32.const 0 + i32.store + local.get $3 + i32.const 8 + i32.sub + i32.const 0 + i32.store + local.get $0 + i32.const 24 + i32.le_u + br_if $~lib/util/memory/memset|inlined.0 + local.get $1 + i32.const 0 + i32.store offset=12 + local.get $1 + i32.const 0 + i32.store offset=16 + local.get $1 + i32.const 0 + i32.store offset=20 + local.get $1 + i32.const 0 + i32.store offset=24 + local.get $3 + i32.const 28 + i32.sub + i32.const 0 + i32.store + local.get $3 + i32.const 24 + i32.sub + i32.const 0 + i32.store + local.get $3 + i32.const 20 + i32.sub + i32.const 0 + i32.store + local.get $3 + i32.const 16 + i32.sub + i32.const 0 + i32.store + local.get $1 + local.get $1 + i32.const 4 + i32.and + i32.const 24 + i32.add + local.tee $3 + i32.add + local.set $1 + local.get $0 + local.get $3 + i32.sub + local.set $0 + loop $while-continue|0 + local.get $0 + i32.const 32 + i32.ge_u + if + local.get $1 + i64.const 0 + i64.store + local.get $1 + i64.const 0 + i64.store offset=8 + local.get $1 + i64.const 0 + i64.store offset=16 + local.get $1 + i64.const 0 + i64.store offset=24 + local.get $0 + i32.const 32 + i32.sub + local.set $0 + local.get $1 + i32.const 32 + i32.add + local.set $1 + br $while-continue|0 + end + end + end + local.get $2 + ) + (func $~lib/rt/itcms/__link (param $0 i32) (param $1 i32) + local.get $1 + i32.eqz + if + return + end + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 294 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/rt/itcms/white + local.get $1 + i32.const 20 + i32.sub + local.tee $1 + i32.load offset=4 + i32.const 3 + i32.and + i32.eq + if + local.get $0 + i32.const 20 + i32.sub + i32.load offset=4 + i32.const 3 + i32.and + local.tee $0 + global.get $~lib/rt/itcms/white + i32.eqz + i32.eq + if + local.get $1 + call $~lib/rt/itcms/Object#makeGray + else + global.get $~lib/rt/itcms/state + i32.const 1 + i32.eq + i32.const 0 + local.get $0 + i32.const 3 + i32.eq + select + if + local.get $1 + call $~lib/rt/itcms/Object#makeGray + end + end + end + ) + (func $~lib/rt/__visit_members (param $0 i32) + (local $1 i32) + block $folding-inner0 + block $invalid + block $duplicate-fields/Bar + block $duplicate-fields/Foo + block $duplicate-fields/B2 + block $duplicate-fields/A + block $duplicate-fields/B + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/B $duplicate-fields/A $duplicate-fields/B2 $folding-inner0 $duplicate-fields/Foo $duplicate-fields/Bar $invalid + end + return + end + return + end + return + end + return + end + local.get $0 + i32.load + local.tee $1 + if + local.get $1 + call $~lib/rt/itcms/__visit + end + local.get $0 + i32.load offset=4 + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + return + end + return + end + return + end + unreachable + end + local.get $0 + i32.load + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + ) + (func $~start + (local $0 i32) + (local $1 i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + block $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 0 + i32.store + memory.size + i32.const 16 + i32.shl + i32.const 17964 + i32.sub + i32.const 1 + i32.shr_u + global.set $~lib/rt/itcms/threshold + i32.const 1172 + i32.const 1168 + i32.store + i32.const 1176 + i32.const 1168 + i32.store + i32.const 1168 + global.set $~lib/rt/itcms/pinSpace + i32.const 1204 + i32.const 1200 + i32.store + i32.const 1208 + i32.const 1200 + i32.store + i32.const 1200 + global.set $~lib/rt/itcms/toSpace + i32.const 1348 + i32.const 1344 + i32.store + i32.const 1352 + i32.const 1344 + i32.store + i32.const 1344 + global.set $~lib/rt/itcms/fromSpace + local.get $0 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 0 + i32.store + local.get $0 + i32.const 8 + i32.const 3 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + local.get $0 + i32.const 0 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + local.tee $1 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 4 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + i32.store + local.get $0 + i32.const 10 + i32.store + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $1 + local.get $0 + i32.store + local.get $0 + i32.const 10 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $0 + global.set $duplicate-fields/foo + global.get $duplicate-fields/foo + i32.load offset=4 + i32.const 10 + i32.ne + if + i32.const 0 + i32.const 1456 + i32.const 13 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 0 + i32.store + local.get $0 + i32.const 8 + i32.const 8 + call $~lib/rt/itcms/__new + local.tee $1 + i32.store + local.get $1 + i32.const 0 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $1 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 7 + call $~lib/rt/itcms/__new + local.tee $1 + i32.store + end + local.get $1 + i32.const 0 + i32.store + local.get $1 + i32.const 1 + i32.store + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $0 + local.get $1 + i32.store + local.get $1 + i32.const 2 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + local.get $1 + i32.store + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 0 + i32.store + local.get $0 + i32.const 8 + i32.const 5 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + local.get $0 + i32.const 0 + i32.store offset=4 + local.get $0 + i32.const 0 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + local.tee $2 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1580 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 6 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + i32.store + local.get $0 + i32.const 0 + call $~lib/rt/itcms/__link + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + local.get $0 + i32.store + local.get $0 + local.get $1 + i32.store offset=4 + local.get $0 + local.get $1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $0 + global.set $duplicate-fields/baz + global.get $duplicate-fields/baz + i32.load offset=4 + i32.load offset=4 + i32.eqz + if + i32.const 0 + i32.const 1456 + i32.const 39 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + return + end + i32.const 17984 + i32.const 18032 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + ) +) diff --git a/tests/compiler/duplicate-fields.ts b/tests/compiler/duplicate-fields.ts new file mode 100644 index 0000000000..150ae1f58f --- /dev/null +++ b/tests/compiler/duplicate-fields.ts @@ -0,0 +1,54 @@ +class A { + bar: i32; + constructor(bar: i32) { this.bar = bar; } +} + +class B extends A { + bar: i32; + constructor(bar: i32) { super(bar); this.bar = bar; } +} + +assert(sizeof() == 4); +const foo = new B(10); +assert(foo.bar == 10); + +// duplicate public fields w/ declare and initializer + +class A2 { + public foo: i32; + public bar: i32; + constructor(foo: i32, bar: i32) { this.foo = foo; this.bar = bar; } +} + +class B2 extends A2 { + public foo: i32 = 1; + declare public bar: i32; + constructor(bar: i32) { this.bar = bar; } +} + +// duplicate fields w/ narrowing + +class Foo { + foo: i32; + constructor(foo: i32) { this.foo = foo; } +} + +class Bar extends Foo { + bar: i32; + constructor(foo: i32, bar: i32) { super(foo); this.bar = bar; } +} + +class A3 { + bar: Foo; + constructor(bar: Foo) { this.bar = bar; } +} + +class B3 extends A3 { + bar: Bar; + constructor(bar: Bar) { super(bar); this.bar = bar; } +} + + +assert(sizeof() == sizeof()); +const baz = new B3(new Bar(1, 2)); +assert(baz.bar.bar); \ No newline at end of file diff --git a/tests/compiler/duplicate-fields.untouched.wat b/tests/compiler/duplicate-fields.untouched.wat new file mode 100644 index 0000000000..e69de29bb2 From 948d23530ec2c80fb56b93c5305d7576ebdc4c77 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 13:40:21 -0600 Subject: [PATCH 02/13] redundant field diagnostic + `declare` parsing --- src/extra/ast.ts | 3 + src/parser.ts | 46 + tests/compiler/duplicate-fields.optimized.wat | 13 +- tests/compiler/duplicate-fields.ts | 28 +- tests/compiler/duplicate-fields.untouched.wat | 2883 +++++++++++++++++ tests/parser/class.ts | 8 + tests/parser/class.ts.fixture.ts | 22 +- 7 files changed, 2968 insertions(+), 35 deletions(-) diff --git a/src/extra/ast.ts b/src/extra/ast.ts index ffa272d1a8..cbffac40fb 100644 --- a/src/extra/ast.ts +++ b/src/extra/ast.ts @@ -1677,6 +1677,9 @@ export class ASTBuilder { serializeAccessModifiers(node: DeclarationStatement): void { var sb = this.sb; + if (node.is(CommonFlags.DECLARE)) { + sb.push("declare "); + } if (node.is(CommonFlags.PUBLIC)) { sb.push("public "); } else if (node.is(CommonFlags.PRIVATE)) { diff --git a/src/parser.ts b/src/parser.ts index 53bbdd0562..07eb01fcee 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1839,6 +1839,7 @@ export class Parser extends DiagnosticEmitter { ): Node | null { // before: + // 'declare'? // ('public' | 'private' | 'protected')? // ('static' | 'abstract')? // 'readonly'? @@ -1870,6 +1871,32 @@ export class Parser extends DiagnosticEmitter { // implemented methods are virtual if (isInterface) flags |= CommonFlags.VIRTUAL; + var declareStart = 0; + var declareEnd = 0; + var contextIsAmbient = parent.is(CommonFlags.AMBIENT); + if (tn.skip(Token.DECLARE)) { + if (isInterface) { + this.error( + DiagnosticCode._0_modifier_cannot_be_used_here, + tn.range(), "declare" + ); + } else { + if (contextIsAmbient) { + this.error( + DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context, + tn.range() + ); // recoverable + } else { + flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT; + declareStart = tn.tokenPos; + declareEnd = tn.pos; + } + } + if (!startPos) startPos = tn.tokenPos; + } else if (contextIsAmbient) { + flags |= CommonFlags.AMBIENT; + } + var accessStart = 0; var accessEnd = 0; if (tn.skip(Token.PUBLIC)) { @@ -1999,6 +2026,12 @@ export class Parser extends DiagnosticEmitter { tn.range(readonlyStart, readonlyEnd), "readonly" ); // recoverable } + if (flags & CommonFlags.DECLARE) { + this.error( + DiagnosticCode._0_modifier_cannot_be_used_here, + tn.range(declareStart, declareEnd), "declare" + ); // recoverable + } } else { tn.reset(state); } @@ -2108,6 +2141,13 @@ export class Parser extends DiagnosticEmitter { // method: '(' Parameters (':' Type)? '{' Statement* '}' ';'? if (tn.skip(Token.OPENPAREN)) { + if (flags & CommonFlags.DECLARE) { + this.error( + DiagnosticCode._0_modifier_cannot_be_used_here, + tn.range(declareStart, declareEnd), "declare" + ); // recoverable + } + let signatureStart = tn.tokenPos; let parameters = this.parseParameters(tn, isConstructor); if (!parameters) return null; @@ -2291,6 +2331,12 @@ export class Parser extends DiagnosticEmitter { } let initializer: Expression | null = null; if (tn.skip(Token.EQUALS)) { + if (flags & CommonFlags.AMBIENT) { + this.error( + DiagnosticCode.Initializers_are_not_allowed_in_ambient_contexts, + tn.range() + ); // recoverable + } initializer = this.parseExpression(tn); if (!initializer) return null; } diff --git a/tests/compiler/duplicate-fields.optimized.wat b/tests/compiler/duplicate-fields.optimized.wat index 3793b5b337..b66877028e 100644 --- a/tests/compiler/duplicate-fields.optimized.wat +++ b/tests/compiler/duplicate-fields.optimized.wat @@ -18,7 +18,7 @@ (global $~lib/rt/itcms/fromSpace (mut i32) (i32.const 0)) (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) (global $duplicate-fields/foo (mut i32) (i32.const 0)) - (global $duplicate-fields/baz (mut i32) (i32.const 0)) + (global $duplicate-fields/raz (mut i32) (i32.const 0)) (global $~lib/memory/__stack_pointer (mut i32) (i32.const 17964)) (memory $0 1) (data (i32.const 1036) "<") @@ -48,7 +48,7 @@ local.get $0 call $~lib/rt/itcms/__visit end - global.get $duplicate-fields/baz + global.get $duplicate-fields/raz local.tee $0 if local.get $0 @@ -2093,15 +2093,16 @@ i32.add global.set $~lib/memory/__stack_pointer local.get $0 - global.set $duplicate-fields/baz - global.get $duplicate-fields/baz + global.set $duplicate-fields/raz + global.get $duplicate-fields/raz i32.load offset=4 i32.load offset=4 - i32.eqz + i32.const 2 + i32.ne if i32.const 0 i32.const 1456 - i32.const 39 + i32.const 40 i32.const 1 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/duplicate-fields.ts b/tests/compiler/duplicate-fields.ts index 150ae1f58f..1fa31dde5e 100644 --- a/tests/compiler/duplicate-fields.ts +++ b/tests/compiler/duplicate-fields.ts @@ -4,28 +4,14 @@ class A { } class B extends A { - bar: i32; + declare bar: i32; constructor(bar: i32) { super(bar); this.bar = bar; } } -assert(sizeof() == 4); +assert(sizeof() == sizeof()); const foo = new B(10); assert(foo.bar == 10); -// duplicate public fields w/ declare and initializer - -class A2 { - public foo: i32; - public bar: i32; - constructor(foo: i32, bar: i32) { this.foo = foo; this.bar = bar; } -} - -class B2 extends A2 { - public foo: i32 = 1; - declare public bar: i32; - constructor(bar: i32) { this.bar = bar; } -} - // duplicate fields w/ narrowing class Foo { @@ -38,17 +24,17 @@ class Bar extends Foo { constructor(foo: i32, bar: i32) { super(foo); this.bar = bar; } } -class A3 { +class A2 { bar: Foo; constructor(bar: Foo) { this.bar = bar; } } -class B3 extends A3 { +class B2 extends A2 { bar: Bar; constructor(bar: Bar) { super(bar); this.bar = bar; } } -assert(sizeof() == sizeof()); -const baz = new B3(new Bar(1, 2)); -assert(baz.bar.bar); \ No newline at end of file +assert(sizeof() == sizeof()); +const raz = new B2(new Bar(1, 2)); +assert(raz.bar.bar == 2); \ No newline at end of file diff --git a/tests/compiler/duplicate-fields.untouched.wat b/tests/compiler/duplicate-fields.untouched.wat index e69de29bb2..db15d779b5 100644 --- a/tests/compiler/duplicate-fields.untouched.wat +++ b/tests/compiler/duplicate-fields.untouched.wat @@ -0,0 +1,2883 @@ +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (global $~lib/rt/itcms/total (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/threshold (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/state (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/visitCount (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/pinSpace (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/iter (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/toSpace (mut i32) (i32.const 0)) + (global $~lib/rt/itcms/white (mut i32) (i32.const 0)) + (global $~lib/shared/runtime/Runtime.Stub i32 (i32.const 0)) + (global $~lib/shared/runtime/Runtime.Minimal i32 (i32.const 1)) + (global $~lib/shared/runtime/Runtime.Incremental i32 (i32.const 2)) + (global $~lib/rt/itcms/fromSpace (mut i32) (i32.const 0)) + (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) + (global $~lib/ASC_LOW_MEMORY_LIMIT i32 (i32.const 0)) + (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) + (global $duplicate-fields/foo (mut i32) (i32.const 0)) + (global $duplicate-fields/raz (mut i32) (i32.const 0)) + (global $~lib/rt/__rtti_base i32 (i32.const 480)) + (global $~lib/memory/__data_end i32 (i32.const 556)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 16940)) + (global $~lib/memory/__heap_base i32 (i32.const 16940)) + (memory $0 1) + (data (i32.const 12) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00(\00\00\00A\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e\00\00\00\00\00") + (data (i32.const 76) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00 \00\00\00~\00l\00i\00b\00/\00r\00t\00/\00i\00t\00c\00m\00s\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 144) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 176) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 204) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00\00\00\00\00\00\00\00\00") + (data (i32.const 268) ",\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s\00\00\00\00\00\00\00\00\00") + (data (i32.const 320) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 348) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 412) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s\00\00\00\00\00\00\00") + (data (i32.const 480) "\t\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\04\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\06\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\07\00\00\00") + (table $0 1 funcref) + (elem $0 (i32.const 1)) + (export "memory" (memory $0)) + (start $~start) + (func $duplicate-fields/A#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + ) + (func $~lib/rt/itcms/Object#set:nextWithColor (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=4 + ) + (func $~lib/rt/itcms/Object#set:prev (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=8 + ) + (func $~lib/rt/itcms/initLazy (param $0 i32) (result i32) + local.get $0 + local.get $0 + call $~lib/rt/itcms/Object#set:nextWithColor + local.get $0 + local.get $0 + call $~lib/rt/itcms/Object#set:prev + local.get $0 + ) + (func $~lib/rt/itcms/Object#get:next (param $0 i32) (result i32) + local.get $0 + i32.load offset=4 + i32.const 3 + i32.const -1 + i32.xor + i32.and + ) + (func $~lib/rt/itcms/Object#get:color (param $0 i32) (result i32) + local.get $0 + i32.load offset=4 + i32.const 3 + i32.and + ) + (func $~lib/rt/itcms/visitRoots (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + local.get $0 + call $~lib/rt/__visit_globals + global.get $~lib/rt/itcms/pinSpace + local.set $1 + local.get $1 + call $~lib/rt/itcms/Object#get:next + local.set $2 + loop $while-continue|0 + local.get $2 + local.get $1 + i32.ne + local.set $3 + local.get $3 + if + i32.const 1 + drop + local.get $2 + call $~lib/rt/itcms/Object#get:color + i32.const 3 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 159 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 20 + i32.add + local.get $0 + call $~lib/rt/__visit_members + local.get $2 + call $~lib/rt/itcms/Object#get:next + local.set $2 + br $while-continue|0 + end + end + ) + (func $~lib/rt/itcms/Object#set:color (param $0 i32) (param $1 i32) + local.get $0 + local.get $0 + i32.load offset=4 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.get $1 + i32.or + call $~lib/rt/itcms/Object#set:nextWithColor + ) + (func $~lib/rt/itcms/Object#set:next (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + local.get $0 + i32.load offset=4 + i32.const 3 + i32.and + i32.or + call $~lib/rt/itcms/Object#set:nextWithColor + ) + (func $~lib/rt/itcms/Object#unlink (param $0 i32) + (local $1 i32) + (local $2 i32) + local.get $0 + call $~lib/rt/itcms/Object#get:next + local.set $1 + local.get $1 + i32.const 0 + i32.eq + if + i32.const 1 + drop + local.get $0 + i32.load offset=8 + i32.const 0 + i32.eq + if (result i32) + local.get $0 + global.get $~lib/memory/__heap_base + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 127 + i32.const 18 + call $~lib/builtins/abort + unreachable + end + return + end + local.get $0 + i32.load offset=8 + local.set $2 + i32.const 1 + drop + local.get $2 + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 131 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $1 + local.get $2 + call $~lib/rt/itcms/Object#set:prev + local.get $2 + local.get $1 + call $~lib/rt/itcms/Object#set:next + ) + (func $~lib/rt/__typeinfo (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/rt/__rtti_base + local.set $1 + local.get $0 + local.get $1 + i32.load + i32.gt_u + if + i32.const 224 + i32.const 288 + i32.const 22 + i32.const 28 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 4 + i32.add + local.get $0 + i32.const 8 + i32.mul + i32.add + i32.load + ) + (func $~lib/rt/itcms/Object#get:isPointerfree (param $0 i32) (result i32) + (local $1 i32) + local.get $0 + i32.load offset=12 + local.set $1 + local.get $1 + i32.const 1 + i32.le_u + if (result i32) + i32.const 1 + else + local.get $1 + call $~lib/rt/__typeinfo + i32.const 32 + i32.and + i32.const 0 + i32.ne + end + ) + (func $~lib/rt/itcms/Object#linkTo (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + local.get $1 + i32.load offset=8 + local.set $3 + local.get $0 + local.get $1 + local.get $2 + i32.or + call $~lib/rt/itcms/Object#set:nextWithColor + local.get $0 + local.get $3 + call $~lib/rt/itcms/Object#set:prev + local.get $3 + local.get $0 + call $~lib/rt/itcms/Object#set:next + local.get $1 + local.get $0 + call $~lib/rt/itcms/Object#set:prev + ) + (func $~lib/rt/itcms/Object#makeGray (param $0 i32) + (local $1 i32) + local.get $0 + global.get $~lib/rt/itcms/iter + i32.eq + if + local.get $0 + i32.load offset=8 + local.tee $1 + i32.eqz + if (result i32) + i32.const 0 + i32.const 96 + i32.const 147 + i32.const 30 + call $~lib/builtins/abort + unreachable + else + local.get $1 + end + global.set $~lib/rt/itcms/iter + end + local.get $0 + call $~lib/rt/itcms/Object#unlink + local.get $0 + global.get $~lib/rt/itcms/toSpace + local.get $0 + call $~lib/rt/itcms/Object#get:isPointerfree + if (result i32) + global.get $~lib/rt/itcms/white + i32.eqz + else + i32.const 2 + end + call $~lib/rt/itcms/Object#linkTo + ) + (func $~lib/rt/itcms/__visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.eqz + if + return + end + local.get $0 + i32.const 20 + i32.sub + local.set $2 + i32.const 0 + drop + local.get $2 + call $~lib/rt/itcms/Object#get:color + global.get $~lib/rt/itcms/white + i32.eq + if + local.get $2 + call $~lib/rt/itcms/Object#makeGray + global.get $~lib/rt/itcms/visitCount + i32.const 1 + i32.add + global.set $~lib/rt/itcms/visitCount + end + ) + (func $~lib/rt/itcms/visitStack (param $0 i32) + (local $1 i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + local.set $1 + loop $while-continue|0 + local.get $1 + global.get $~lib/memory/__heap_base + i32.lt_u + local.set $2 + local.get $2 + if + local.get $1 + i32.load + local.get $0 + call $~lib/rt/itcms/__visit + local.get $1 + i32.const 4 + i32.add + local.set $1 + br $while-continue|0 + end + end + ) + (func $~lib/rt/itcms/Object#get:size (param $0 i32) (result i32) + i32.const 4 + local.get $0 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + ) + (func $~lib/rt/tlsf/Root#set:flMap (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + ) + (func $~lib/rt/common/BLOCK#set:mmInfo (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + ) + (func $~lib/rt/tlsf/Block#set:prev (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=4 + ) + (func $~lib/rt/tlsf/Block#set:next (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=8 + ) + (func $~lib/rt/tlsf/removeBlock (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + local.get $1 + i32.load + local.set $2 + i32.const 1 + drop + local.get $2 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 268 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.set $3 + i32.const 1 + drop + local.get $3 + i32.const 12 + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 270 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const 256 + i32.lt_u + if + i32.const 0 + local.set $4 + local.get $3 + i32.const 4 + i32.shr_u + local.set $5 + else + local.get $3 + local.tee $6 + i32.const 1073741820 + local.tee $7 + local.get $6 + local.get $7 + i32.lt_u + select + local.set $6 + i32.const 31 + local.get $6 + i32.clz + i32.sub + local.set $4 + local.get $6 + local.get $4 + i32.const 4 + i32.sub + i32.shr_u + i32.const 1 + i32.const 4 + i32.shl + i32.xor + local.set $5 + local.get $4 + i32.const 8 + i32.const 1 + i32.sub + i32.sub + local.set $4 + end + i32.const 1 + drop + local.get $4 + i32.const 23 + i32.lt_u + if (result i32) + local.get $5 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 284 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load offset=4 + local.set $8 + local.get $1 + i32.load offset=8 + local.set $9 + local.get $8 + if + local.get $8 + local.get $9 + call $~lib/rt/tlsf/Block#set:next + end + local.get $9 + if + local.get $9 + local.get $8 + call $~lib/rt/tlsf/Block#set:prev + end + local.get $1 + local.get $0 + local.set $10 + local.get $4 + local.set $6 + local.get $5 + local.set $7 + local.get $10 + local.get $6 + i32.const 4 + i32.shl + local.get $7 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + i32.eq + if + local.get $0 + local.set $11 + local.get $4 + local.set $10 + local.get $5 + local.set $6 + local.get $9 + local.set $7 + local.get $11 + local.get $10 + i32.const 4 + i32.shl + local.get $6 + i32.add + i32.const 2 + i32.shl + i32.add + local.get $7 + i32.store offset=96 + local.get $9 + i32.eqz + if + local.get $0 + local.set $6 + local.get $4 + local.set $7 + local.get $6 + local.get $7 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + local.set $6 + local.get $0 + local.set $7 + local.get $4 + local.set $11 + local.get $6 + i32.const 1 + local.get $5 + i32.shl + i32.const -1 + i32.xor + i32.and + local.tee $6 + local.set $10 + local.get $7 + local.get $11 + i32.const 2 + i32.shl + i32.add + local.get $10 + i32.store offset=4 + local.get $6 + i32.eqz + if + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $4 + i32.shl + i32.const -1 + i32.xor + i32.and + call $~lib/rt/tlsf/Root#set:flMap + end + end + end + ) + (func $~lib/rt/tlsf/insertBlock (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + i32.const 1 + drop + local.get $1 + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 201 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load + local.set $2 + i32.const 1 + drop + local.get $2 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 203 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + local.set $3 + local.get $3 + i32.const 4 + i32.add + local.get $3 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.set $4 + local.get $4 + i32.load + local.set $5 + local.get $5 + i32.const 1 + i32.and + if + local.get $0 + local.get $4 + call $~lib/rt/tlsf/removeBlock + local.get $1 + local.get $2 + i32.const 4 + i32.add + local.get $5 + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.tee $2 + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $1 + local.set $3 + local.get $3 + i32.const 4 + i32.add + local.get $3 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.set $4 + local.get $4 + i32.load + local.set $5 + end + local.get $2 + i32.const 2 + i32.and + if + local.get $1 + local.set $3 + local.get $3 + i32.const 4 + i32.sub + i32.load + local.set $3 + local.get $3 + i32.load + local.set $6 + i32.const 1 + drop + local.get $6 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 221 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $3 + call $~lib/rt/tlsf/removeBlock + local.get $3 + local.set $1 + local.get $1 + local.get $6 + i32.const 4 + i32.add + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.tee $2 + call $~lib/rt/common/BLOCK#set:mmInfo + end + local.get $4 + local.get $5 + i32.const 2 + i32.or + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.set $7 + i32.const 1 + drop + local.get $7 + i32.const 12 + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 233 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + drop + local.get $1 + i32.const 4 + i32.add + local.get $7 + i32.add + local.get $4 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 234 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $4 + i32.const 4 + i32.sub + local.get $1 + i32.store + local.get $7 + i32.const 256 + i32.lt_u + if + i32.const 0 + local.set $8 + local.get $7 + i32.const 4 + i32.shr_u + local.set $9 + else + local.get $7 + local.tee $3 + i32.const 1073741820 + local.tee $6 + local.get $3 + local.get $6 + i32.lt_u + select + local.set $3 + i32.const 31 + local.get $3 + i32.clz + i32.sub + local.set $8 + local.get $3 + local.get $8 + i32.const 4 + i32.sub + i32.shr_u + i32.const 1 + i32.const 4 + i32.shl + i32.xor + local.set $9 + local.get $8 + i32.const 8 + i32.const 1 + i32.sub + i32.sub + local.set $8 + end + i32.const 1 + drop + local.get $8 + i32.const 23 + i32.lt_u + if (result i32) + local.get $9 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 251 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $10 + local.get $8 + local.set $3 + local.get $9 + local.set $6 + local.get $10 + local.get $3 + i32.const 4 + i32.shl + local.get $6 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $11 + local.get $1 + i32.const 0 + call $~lib/rt/tlsf/Block#set:prev + local.get $1 + local.get $11 + call $~lib/rt/tlsf/Block#set:next + local.get $11 + if + local.get $11 + local.get $1 + call $~lib/rt/tlsf/Block#set:prev + end + local.get $0 + local.set $12 + local.get $8 + local.set $10 + local.get $9 + local.set $3 + local.get $1 + local.set $6 + local.get $12 + local.get $10 + i32.const 4 + i32.shl + local.get $3 + i32.add + i32.const 2 + i32.shl + i32.add + local.get $6 + i32.store offset=96 + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $8 + i32.shl + i32.or + call $~lib/rt/tlsf/Root#set:flMap + local.get $0 + local.set $13 + local.get $8 + local.set $12 + local.get $0 + local.set $3 + local.get $8 + local.set $6 + local.get $3 + local.get $6 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const 1 + local.get $9 + i32.shl + i32.or + local.set $10 + local.get $13 + local.get $12 + i32.const 2 + i32.shl + i32.add + local.get $10 + i32.store offset=4 + ) + (func $~lib/rt/tlsf/addMemory (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + i32.const 1 + drop + local.get $1 + local.get $2 + i32.le_u + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 377 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 4 + i32.add + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + i32.const 4 + i32.sub + local.set $1 + local.get $2 + i32.const 15 + i32.const -1 + i32.xor + i32.and + local.set $2 + local.get $0 + local.set $3 + local.get $3 + i32.load offset=1568 + local.set $4 + i32.const 0 + local.set $5 + local.get $4 + if + i32.const 1 + drop + local.get $1 + local.get $4 + i32.const 4 + i32.add + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 384 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 16 + i32.sub + local.get $4 + i32.eq + if + local.get $1 + i32.const 16 + i32.sub + local.set $1 + local.get $4 + i32.load + local.set $5 + else + nop + end + else + i32.const 1 + drop + local.get $1 + local.get $0 + i32.const 1572 + i32.add + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 397 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + end + local.get $2 + local.get $1 + i32.sub + local.set $6 + local.get $6 + i32.const 4 + i32.const 12 + i32.add + i32.const 4 + i32.add + i32.lt_u + if + i32.const 0 + return + end + local.get $6 + i32.const 2 + i32.const 4 + i32.mul + i32.sub + local.set $7 + local.get $1 + local.set $8 + local.get $8 + local.get $7 + i32.const 1 + i32.or + local.get $5 + i32.const 2 + i32.and + i32.or + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $8 + i32.const 0 + call $~lib/rt/tlsf/Block#set:prev + local.get $8 + i32.const 0 + call $~lib/rt/tlsf/Block#set:next + local.get $1 + i32.const 4 + i32.add + local.get $7 + i32.add + local.set $4 + local.get $4 + i32.const 0 + i32.const 2 + i32.or + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $0 + local.set $9 + local.get $4 + local.set $3 + local.get $9 + local.get $3 + i32.store offset=1568 + local.get $0 + local.get $8 + call $~lib/rt/tlsf/insertBlock + i32.const 1 + ) + (func $~lib/rt/tlsf/initialize + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + i32.const 0 + drop + global.get $~lib/memory/__heap_base + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + local.set $0 + memory.size + local.set $1 + local.get $0 + i32.const 1572 + i32.add + i32.const 65535 + i32.add + i32.const 65535 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.shr_u + local.set $2 + local.get $2 + local.get $1 + i32.gt_s + if (result i32) + local.get $2 + local.get $1 + i32.sub + memory.grow + i32.const 0 + i32.lt_s + else + i32.const 0 + end + if + unreachable + end + local.get $0 + local.set $3 + local.get $3 + i32.const 0 + call $~lib/rt/tlsf/Root#set:flMap + local.get $3 + local.set $5 + i32.const 0 + local.set $4 + local.get $5 + local.get $4 + i32.store offset=1568 + i32.const 0 + local.set $5 + loop $for-loop|0 + local.get $5 + i32.const 23 + i32.lt_u + local.set $4 + local.get $4 + if + local.get $3 + local.set $8 + local.get $5 + local.set $7 + i32.const 0 + local.set $6 + local.get $8 + local.get $7 + i32.const 2 + i32.shl + i32.add + local.get $6 + i32.store offset=4 + i32.const 0 + local.set $8 + loop $for-loop|1 + local.get $8 + i32.const 16 + i32.lt_u + local.set $7 + local.get $7 + if + local.get $3 + local.set $11 + local.get $5 + local.set $10 + local.get $8 + local.set $9 + i32.const 0 + local.set $6 + local.get $11 + local.get $10 + i32.const 4 + i32.shl + local.get $9 + i32.add + i32.const 2 + i32.shl + i32.add + local.get $6 + i32.store offset=96 + local.get $8 + i32.const 1 + i32.add + local.set $8 + br $for-loop|1 + end + end + local.get $5 + i32.const 1 + i32.add + local.set $5 + br $for-loop|0 + end + end + local.get $0 + i32.const 1572 + i32.add + local.set $12 + i32.const 0 + drop + local.get $3 + local.get $12 + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + drop + local.get $3 + global.set $~lib/rt/tlsf/ROOT + ) + (func $~lib/rt/tlsf/checkUsedBlock (param $0 i32) (result i32) + (local $1 i32) + local.get $0 + i32.const 4 + i32.sub + local.set $1 + local.get $0 + i32.const 0 + i32.ne + if (result i32) + local.get $0 + i32.const 15 + i32.and + i32.eqz + else + i32.const 0 + end + if (result i32) + local.get $1 + i32.load + i32.const 1 + i32.and + i32.eqz + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 559 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + local.get $1 + ) + (func $~lib/rt/tlsf/freeBlock (param $0 i32) (param $1 i32) + i32.const 0 + drop + local.get $1 + local.get $1 + i32.load + i32.const 1 + i32.or + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $0 + local.get $1 + call $~lib/rt/tlsf/insertBlock + ) + (func $~lib/rt/tlsf/__free (param $0 i32) + local.get $0 + global.get $~lib/memory/__heap_base + i32.lt_u + if + return + end + global.get $~lib/rt/tlsf/ROOT + i32.eqz + if + call $~lib/rt/tlsf/initialize + end + global.get $~lib/rt/tlsf/ROOT + local.get $0 + call $~lib/rt/tlsf/checkUsedBlock + call $~lib/rt/tlsf/freeBlock + ) + (func $~lib/rt/itcms/free (param $0 i32) + local.get $0 + global.get $~lib/memory/__heap_base + i32.lt_u + if + local.get $0 + i32.const 0 + call $~lib/rt/itcms/Object#set:nextWithColor + local.get $0 + i32.const 0 + call $~lib/rt/itcms/Object#set:prev + else + global.get $~lib/rt/itcms/total + local.get $0 + call $~lib/rt/itcms/Object#get:size + i32.sub + global.set $~lib/rt/itcms/total + i32.const 0 + drop + local.get $0 + i32.const 4 + i32.add + call $~lib/rt/tlsf/__free + end + ) + (func $~lib/rt/itcms/step (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + block $break|0 + block $case2|0 + block $case1|0 + block $case0|0 + global.get $~lib/rt/itcms/state + local.set $1 + local.get $1 + i32.const 0 + i32.eq + br_if $case0|0 + local.get $1 + i32.const 1 + i32.eq + br_if $case1|0 + local.get $1 + i32.const 2 + i32.eq + br_if $case2|0 + br $break|0 + end + i32.const 1 + global.set $~lib/rt/itcms/state + i32.const 0 + global.set $~lib/rt/itcms/visitCount + i32.const 0 + call $~lib/rt/itcms/visitRoots + global.get $~lib/rt/itcms/toSpace + global.set $~lib/rt/itcms/iter + global.get $~lib/rt/itcms/visitCount + i32.const 1 + i32.mul + return + end + global.get $~lib/rt/itcms/white + i32.eqz + local.set $1 + global.get $~lib/rt/itcms/iter + call $~lib/rt/itcms/Object#get:next + local.set $0 + loop $while-continue|1 + local.get $0 + global.get $~lib/rt/itcms/toSpace + i32.ne + local.set $2 + local.get $2 + if + local.get $0 + global.set $~lib/rt/itcms/iter + local.get $0 + call $~lib/rt/itcms/Object#get:color + local.get $1 + i32.ne + if + local.get $0 + local.get $1 + call $~lib/rt/itcms/Object#set:color + i32.const 0 + global.set $~lib/rt/itcms/visitCount + local.get $0 + i32.const 20 + i32.add + i32.const 0 + call $~lib/rt/__visit_members + global.get $~lib/rt/itcms/visitCount + i32.const 1 + i32.mul + return + end + local.get $0 + call $~lib/rt/itcms/Object#get:next + local.set $0 + br $while-continue|1 + end + end + i32.const 0 + global.set $~lib/rt/itcms/visitCount + i32.const 0 + call $~lib/rt/itcms/visitRoots + global.get $~lib/rt/itcms/iter + call $~lib/rt/itcms/Object#get:next + local.set $0 + local.get $0 + global.get $~lib/rt/itcms/toSpace + i32.eq + if + i32.const 0 + call $~lib/rt/itcms/visitStack + global.get $~lib/rt/itcms/iter + call $~lib/rt/itcms/Object#get:next + local.set $0 + loop $while-continue|2 + local.get $0 + global.get $~lib/rt/itcms/toSpace + i32.ne + local.set $2 + local.get $2 + if + local.get $0 + call $~lib/rt/itcms/Object#get:color + local.get $1 + i32.ne + if + local.get $0 + local.get $1 + call $~lib/rt/itcms/Object#set:color + local.get $0 + i32.const 20 + i32.add + i32.const 0 + call $~lib/rt/__visit_members + end + local.get $0 + call $~lib/rt/itcms/Object#get:next + local.set $0 + br $while-continue|2 + end + end + global.get $~lib/rt/itcms/fromSpace + local.set $2 + global.get $~lib/rt/itcms/toSpace + global.set $~lib/rt/itcms/fromSpace + local.get $2 + global.set $~lib/rt/itcms/toSpace + local.get $1 + global.set $~lib/rt/itcms/white + local.get $2 + call $~lib/rt/itcms/Object#get:next + global.set $~lib/rt/itcms/iter + i32.const 2 + global.set $~lib/rt/itcms/state + end + global.get $~lib/rt/itcms/visitCount + i32.const 1 + i32.mul + return + end + global.get $~lib/rt/itcms/iter + local.set $0 + local.get $0 + global.get $~lib/rt/itcms/toSpace + i32.ne + if + local.get $0 + call $~lib/rt/itcms/Object#get:next + global.set $~lib/rt/itcms/iter + i32.const 1 + drop + local.get $0 + call $~lib/rt/itcms/Object#get:color + global.get $~lib/rt/itcms/white + i32.eqz + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 228 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + local.get $0 + call $~lib/rt/itcms/free + i32.const 10 + return + end + global.get $~lib/rt/itcms/toSpace + global.get $~lib/rt/itcms/toSpace + call $~lib/rt/itcms/Object#set:nextWithColor + global.get $~lib/rt/itcms/toSpace + global.get $~lib/rt/itcms/toSpace + call $~lib/rt/itcms/Object#set:prev + i32.const 0 + global.set $~lib/rt/itcms/state + br $break|0 + end + i32.const 0 + ) + (func $~lib/rt/itcms/interrupt + (local $0 i32) + i32.const 0 + drop + i32.const 0 + drop + i32.const 1024 + i32.const 200 + i32.mul + i32.const 100 + i32.div_u + local.set $0 + loop $do-loop|0 + local.get $0 + call $~lib/rt/itcms/step + i32.sub + local.set $0 + global.get $~lib/rt/itcms/state + i32.const 0 + i32.eq + if + i32.const 0 + drop + global.get $~lib/rt/itcms/total + i64.extend_i32_u + i32.const 200 + i64.extend_i32_u + i64.mul + i64.const 100 + i64.div_u + i32.wrap_i64 + i32.const 1024 + i32.add + global.set $~lib/rt/itcms/threshold + i32.const 0 + drop + return + end + local.get $0 + i32.const 0 + i32.gt_s + br_if $do-loop|0 + end + i32.const 0 + drop + global.get $~lib/rt/itcms/total + i32.const 1024 + global.get $~lib/rt/itcms/total + global.get $~lib/rt/itcms/threshold + i32.sub + i32.const 1024 + i32.lt_u + i32.mul + i32.add + global.set $~lib/rt/itcms/threshold + i32.const 0 + drop + ) + (func $~lib/rt/tlsf/computeSize (param $0 i32) (result i32) + local.get $0 + i32.const 12 + i32.le_u + if (result i32) + i32.const 12 + else + local.get $0 + i32.const 4 + i32.add + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + i32.const 4 + i32.sub + end + ) + (func $~lib/rt/tlsf/prepareSize (param $0 i32) (result i32) + local.get $0 + i32.const 1073741820 + i32.gt_u + if + i32.const 32 + i32.const 368 + i32.const 458 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + local.get $0 + call $~lib/rt/tlsf/computeSize + ) + (func $~lib/rt/tlsf/searchBlock (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + local.get $1 + i32.const 256 + i32.lt_u + if + i32.const 0 + local.set $2 + local.get $1 + i32.const 4 + i32.shr_u + local.set $3 + else + local.get $1 + i32.const 536870910 + i32.lt_u + if (result i32) + local.get $1 + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + i32.add + i32.const 1 + i32.sub + else + local.get $1 + end + local.set $4 + i32.const 31 + local.get $4 + i32.clz + i32.sub + local.set $2 + local.get $4 + local.get $2 + i32.const 4 + i32.sub + i32.shr_u + i32.const 1 + i32.const 4 + i32.shl + i32.xor + local.set $3 + local.get $2 + i32.const 8 + i32.const 1 + i32.sub + i32.sub + local.set $2 + end + i32.const 1 + drop + local.get $2 + i32.const 23 + i32.lt_u + if (result i32) + local.get $3 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 330 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $5 + local.get $2 + local.set $4 + local.get $5 + local.get $4 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const 0 + i32.const -1 + i32.xor + local.get $3 + i32.shl + i32.and + local.set $6 + i32.const 0 + local.set $7 + local.get $6 + i32.eqz + if + local.get $0 + i32.load + i32.const 0 + i32.const -1 + i32.xor + local.get $2 + i32.const 1 + i32.add + i32.shl + i32.and + local.set $5 + local.get $5 + i32.eqz + if + i32.const 0 + local.set $7 + else + local.get $5 + i32.ctz + local.set $2 + local.get $0 + local.set $8 + local.get $2 + local.set $4 + local.get $8 + local.get $4 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + local.set $6 + i32.const 1 + drop + local.get $6 + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 343 + i32.const 18 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $9 + local.get $2 + local.set $8 + local.get $6 + i32.ctz + local.set $4 + local.get $9 + local.get $8 + i32.const 4 + i32.shl + local.get $4 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $7 + end + else + local.get $0 + local.set $9 + local.get $2 + local.set $8 + local.get $6 + i32.ctz + local.set $4 + local.get $9 + local.get $8 + i32.const 4 + i32.shl + local.get $4 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $7 + end + local.get $7 + ) + (func $~lib/rt/tlsf/growMemory (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + i32.const 0 + drop + local.get $1 + i32.const 536870910 + i32.lt_u + if + local.get $1 + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + i32.const 1 + i32.sub + i32.add + local.set $1 + end + memory.size + local.set $2 + local.get $1 + i32.const 4 + local.get $2 + i32.const 16 + i32.shl + i32.const 4 + i32.sub + local.get $0 + local.set $3 + local.get $3 + i32.load offset=1568 + i32.ne + i32.shl + i32.add + local.set $1 + local.get $1 + i32.const 65535 + i32.add + i32.const 65535 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.shr_u + local.set $4 + local.get $2 + local.tee $3 + local.get $4 + local.tee $5 + local.get $3 + local.get $5 + i32.gt_s + select + local.set $6 + local.get $6 + memory.grow + i32.const 0 + i32.lt_s + if + local.get $4 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + memory.size + local.set $7 + local.get $0 + local.get $2 + i32.const 16 + i32.shl + local.get $7 + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + drop + ) + (func $~lib/rt/tlsf/prepareBlock (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + local.get $1 + i32.load + local.set $3 + i32.const 1 + drop + local.get $2 + i32.const 4 + i32.add + i32.const 15 + i32.and + i32.eqz + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 357 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.get $2 + i32.sub + local.set $4 + local.get $4 + i32.const 4 + i32.const 12 + i32.add + i32.ge_u + if + local.get $1 + local.get $2 + local.get $3 + i32.const 2 + i32.and + i32.or + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $1 + i32.const 4 + i32.add + local.get $2 + i32.add + local.set $5 + local.get $5 + local.get $4 + i32.const 4 + i32.sub + i32.const 1 + i32.or + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $0 + local.get $5 + call $~lib/rt/tlsf/insertBlock + else + local.get $1 + local.get $3 + i32.const 1 + i32.const -1 + i32.xor + i32.and + call $~lib/rt/common/BLOCK#set:mmInfo + local.get $1 + local.set $5 + local.get $5 + i32.const 4 + i32.add + local.get $5 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.get $1 + local.set $5 + local.get $5 + i32.const 4 + i32.add + local.get $5 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + i32.load + i32.const 2 + i32.const -1 + i32.xor + i32.and + call $~lib/rt/common/BLOCK#set:mmInfo + end + ) + (func $~lib/rt/tlsf/allocateBlock (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + local.get $1 + call $~lib/rt/tlsf/prepareSize + local.set $2 + local.get $0 + local.get $2 + call $~lib/rt/tlsf/searchBlock + local.set $3 + local.get $3 + i32.eqz + if + local.get $0 + local.get $2 + call $~lib/rt/tlsf/growMemory + local.get $0 + local.get $2 + call $~lib/rt/tlsf/searchBlock + local.set $3 + i32.const 1 + drop + local.get $3 + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 496 + i32.const 16 + call $~lib/builtins/abort + unreachable + end + end + i32.const 1 + drop + local.get $3 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.get $2 + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 368 + i32.const 498 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $3 + call $~lib/rt/tlsf/removeBlock + local.get $0 + local.get $3 + local.get $2 + call $~lib/rt/tlsf/prepareBlock + i32.const 0 + drop + local.get $3 + ) + (func $~lib/rt/tlsf/__alloc (param $0 i32) (result i32) + global.get $~lib/rt/tlsf/ROOT + i32.eqz + if + call $~lib/rt/tlsf/initialize + end + global.get $~lib/rt/tlsf/ROOT + local.get $0 + call $~lib/rt/tlsf/allocateBlock + i32.const 4 + i32.add + ) + (func $~lib/rt/itcms/Object#set:rtId (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=12 + ) + (func $~lib/rt/itcms/Object#set:rtSize (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=16 + ) + (func $~lib/memory/memory.fill (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i64) + (local $10 i32) + block $~lib/util/memory/memset|inlined.0 + local.get $0 + local.set $5 + local.get $1 + local.set $4 + local.get $2 + local.set $3 + i32.const 0 + i32.const 1 + i32.gt_s + drop + local.get $3 + i32.eqz + if + br $~lib/util/memory/memset|inlined.0 + end + local.get $5 + local.get $3 + i32.add + local.set $6 + local.get $5 + local.get $4 + i32.store8 + local.get $6 + i32.const 1 + i32.sub + local.get $4 + i32.store8 + local.get $3 + i32.const 2 + i32.le_u + if + br $~lib/util/memory/memset|inlined.0 + end + local.get $5 + local.get $4 + i32.store8 offset=1 + local.get $5 + local.get $4 + i32.store8 offset=2 + local.get $6 + i32.const 2 + i32.sub + local.get $4 + i32.store8 + local.get $6 + i32.const 3 + i32.sub + local.get $4 + i32.store8 + local.get $3 + i32.const 6 + i32.le_u + if + br $~lib/util/memory/memset|inlined.0 + end + local.get $5 + local.get $4 + i32.store8 offset=3 + local.get $6 + i32.const 4 + i32.sub + local.get $4 + i32.store8 + local.get $3 + i32.const 8 + i32.le_u + if + br $~lib/util/memory/memset|inlined.0 + end + i32.const 0 + local.get $5 + i32.sub + i32.const 3 + i32.and + local.set $7 + local.get $5 + local.get $7 + i32.add + local.set $5 + local.get $3 + local.get $7 + i32.sub + local.set $3 + local.get $3 + i32.const -4 + i32.and + local.set $3 + i32.const -1 + i32.const 255 + i32.div_u + local.get $4 + i32.const 255 + i32.and + i32.mul + local.set $8 + local.get $5 + local.get $3 + i32.add + local.set $6 + local.get $5 + local.get $8 + i32.store + local.get $6 + i32.const 4 + i32.sub + local.get $8 + i32.store + local.get $3 + i32.const 8 + i32.le_u + if + br $~lib/util/memory/memset|inlined.0 + end + local.get $5 + local.get $8 + i32.store offset=4 + local.get $5 + local.get $8 + i32.store offset=8 + local.get $6 + i32.const 12 + i32.sub + local.get $8 + i32.store + local.get $6 + i32.const 8 + i32.sub + local.get $8 + i32.store + local.get $3 + i32.const 24 + i32.le_u + if + br $~lib/util/memory/memset|inlined.0 + end + local.get $5 + local.get $8 + i32.store offset=12 + local.get $5 + local.get $8 + i32.store offset=16 + local.get $5 + local.get $8 + i32.store offset=20 + local.get $5 + local.get $8 + i32.store offset=24 + local.get $6 + i32.const 28 + i32.sub + local.get $8 + i32.store + local.get $6 + i32.const 24 + i32.sub + local.get $8 + i32.store + local.get $6 + i32.const 20 + i32.sub + local.get $8 + i32.store + local.get $6 + i32.const 16 + i32.sub + local.get $8 + i32.store + i32.const 24 + local.get $5 + i32.const 4 + i32.and + i32.add + local.set $7 + local.get $5 + local.get $7 + i32.add + local.set $5 + local.get $3 + local.get $7 + i32.sub + local.set $3 + local.get $8 + i64.extend_i32_u + local.get $8 + i64.extend_i32_u + i64.const 32 + i64.shl + i64.or + local.set $9 + loop $while-continue|0 + local.get $3 + i32.const 32 + i32.ge_u + local.set $10 + local.get $10 + if + local.get $5 + local.get $9 + i64.store + local.get $5 + local.get $9 + i64.store offset=8 + local.get $5 + local.get $9 + i64.store offset=16 + local.get $5 + local.get $9 + i64.store offset=24 + local.get $3 + i32.const 32 + i32.sub + local.set $3 + local.get $5 + i32.const 32 + i32.add + local.set $5 + br $while-continue|0 + end + end + end + ) + (func $~lib/rt/itcms/__new (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + local.get $0 + i32.const 1073741804 + i32.ge_u + if + i32.const 32 + i32.const 96 + i32.const 260 + i32.const 31 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/rt/itcms/total + global.get $~lib/rt/itcms/threshold + i32.ge_u + if + call $~lib/rt/itcms/interrupt + end + i32.const 16 + local.get $0 + i32.add + call $~lib/rt/tlsf/__alloc + i32.const 4 + i32.sub + local.set $2 + local.get $2 + local.get $1 + call $~lib/rt/itcms/Object#set:rtId + local.get $2 + local.get $0 + call $~lib/rt/itcms/Object#set:rtSize + local.get $2 + global.get $~lib/rt/itcms/fromSpace + global.get $~lib/rt/itcms/white + call $~lib/rt/itcms/Object#linkTo + global.get $~lib/rt/itcms/total + local.get $2 + call $~lib/rt/itcms/Object#get:size + i32.add + global.set $~lib/rt/itcms/total + local.get $2 + i32.const 20 + i32.add + local.set $3 + local.get $3 + i32.const 0 + local.get $0 + call $~lib/memory/memory.fill + local.get $3 + ) + (func $duplicate-fields/B#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=4 + ) + (func $~lib/rt/itcms/__link (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + local.get $1 + i32.eqz + if + return + end + i32.const 1 + drop + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 294 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 20 + i32.sub + local.set $3 + local.get $3 + call $~lib/rt/itcms/Object#get:color + global.get $~lib/rt/itcms/white + i32.eq + if + local.get $0 + i32.const 20 + i32.sub + local.set $4 + local.get $4 + call $~lib/rt/itcms/Object#get:color + local.set $5 + local.get $5 + global.get $~lib/rt/itcms/white + i32.eqz + i32.eq + if + local.get $2 + if + local.get $4 + call $~lib/rt/itcms/Object#makeGray + else + local.get $3 + call $~lib/rt/itcms/Object#makeGray + end + else + local.get $5 + i32.const 3 + i32.eq + if (result i32) + global.get $~lib/rt/itcms/state + i32.const 1 + i32.eq + else + i32.const 0 + end + if + local.get $3 + call $~lib/rt/itcms/Object#makeGray + end + end + end + ) + (func $duplicate-fields/A2#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + ) + (func $duplicate-fields/B2#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=4 + local.get $0 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + ) + (func $duplicate-fields/Foo#set:foo (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + ) + (func $duplicate-fields/Bar#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=4 + ) + (func $~lib/rt/__visit_globals (param $0 i32) + (local $1 i32) + global.get $duplicate-fields/foo + local.tee $1 + if + local.get $1 + local.get $0 + call $~lib/rt/itcms/__visit + end + global.get $duplicate-fields/raz + local.tee $1 + if + local.get $1 + local.get $0 + call $~lib/rt/itcms/__visit + end + i32.const 224 + local.get $0 + call $~lib/rt/itcms/__visit + i32.const 32 + local.get $0 + call $~lib/rt/itcms/__visit + ) + (func $~lib/arraybuffer/ArrayBufferView~visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + ) + (func $duplicate-fields/B2~visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + local.get $1 + call $duplicate-fields/A2~visit + local.get $0 + i32.load offset=4 + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + ) + (func $duplicate-fields/A2~visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + ) + (func $~lib/rt/__visit_members (param $0 i32) (param $1 i32) + block $invalid + block $duplicate-fields/Bar + block $duplicate-fields/Foo + block $duplicate-fields/A2 + block $duplicate-fields/B2 + block $duplicate-fields/A + block $duplicate-fields/B + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $duplicate-fields/B $duplicate-fields/A $duplicate-fields/B2 $duplicate-fields/A2 $duplicate-fields/Foo $duplicate-fields/Bar $invalid + end + return + end + return + end + local.get $0 + local.get $1 + call $~lib/arraybuffer/ArrayBufferView~visit + return + end + return + end + return + end + local.get $0 + local.get $1 + call $duplicate-fields/B2~visit + return + end + local.get $0 + local.get $1 + call $duplicate-fields/A2~visit + return + end + return + end + return + end + unreachable + ) + (func $~start + call $start:duplicate-fields + ) + (func $~stack_check + global.get $~lib/memory/__stack_pointer + global.get $~lib/memory/__data_end + i32.lt_s + if + i32.const 16960 + i32.const 17008 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + ) + (func $start:duplicate-fields + (local $0 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + i32.const 4 + i32.const 4 + i32.eq + drop + memory.size + i32.const 16 + i32.shl + global.get $~lib/memory/__heap_base + i32.sub + i32.const 1 + i32.shr_u + global.set $~lib/rt/itcms/threshold + i32.const 144 + call $~lib/rt/itcms/initLazy + global.set $~lib/rt/itcms/pinSpace + i32.const 176 + call $~lib/rt/itcms/initLazy + global.set $~lib/rt/itcms/toSpace + i32.const 320 + call $~lib/rt/itcms/initLazy + global.set $~lib/rt/itcms/fromSpace + i32.const 0 + i32.const 10 + call $duplicate-fields/B#constructor + global.set $duplicate-fields/foo + global.get $duplicate-fields/foo + i32.load offset=4 + i32.const 10 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 432 + i32.const 13 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 4 + i32.const 4 + i32.eq + drop + i32.const 0 + i32.const 0 + i32.const 1 + i32.const 2 + call $duplicate-fields/Bar#constructor + local.set $0 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + call $duplicate-fields/B2#constructor + global.set $duplicate-fields/raz + global.get $duplicate-fields/raz + i32.load offset=4 + i32.load offset=4 + i32.const 2 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 432 + i32.const 40 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $duplicate-fields/A#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 4 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/A#set:bar + local.get $0 + local.get $1 + call $duplicate-fields/A#set:bar + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $duplicate-fields/B#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.const 3 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/B#set:bar + global.get $~lib/memory/__stack_pointer + local.get $0 + local.get $1 + call $duplicate-fields/A#constructor + local.tee $0 + i32.store + local.get $0 + local.get $1 + call $duplicate-fields/B#set:bar + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $duplicate-fields/A2#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 6 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/A2#set:bar + local.get $0 + local.get $1 + call $duplicate-fields/A2#set:bar + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $duplicate-fields/B2#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.const 5 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/B2#set:bar + global.get $~lib/memory/__stack_pointer + local.get $0 + local.get $1 + call $duplicate-fields/A2#constructor + local.tee $0 + i32.store + local.get $0 + local.get $1 + call $duplicate-fields/B2#set:bar + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $duplicate-fields/Foo#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 7 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/Foo#set:foo + local.get $0 + local.get $1 + call $duplicate-fields/Foo#set:foo + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $duplicate-fields/Bar#constructor (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.const 8 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/Bar#set:bar + global.get $~lib/memory/__stack_pointer + local.get $0 + local.get $1 + call $duplicate-fields/Foo#constructor + local.tee $0 + i32.store + local.get $0 + local.get $2 + call $duplicate-fields/Bar#set:bar + local.get $0 + local.set $3 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $3 + ) +) diff --git a/tests/parser/class.ts b/tests/parser/class.ts index e80a34b527..20470aa0aa 100644 --- a/tests/parser/class.ts +++ b/tests/parser/class.ts @@ -8,6 +8,7 @@ export class Valid { static staticField: i32; static void: i32; void: i32 = Valid.void; + declare declareField: i32; } export class Invalid { @@ -26,4 +27,11 @@ export class Invalid { // 1049: A 'set' accessor must have exactly one parameter. // 1095: A 'set' accessor cannot have a return type annotation. set instanceSetter(): i32 {} + + // 1039: Initializers are not allowed in ambient contexts. + declare declareInitializer: i32 = 1; + + // 1042: 'declare' modifier cannot be used here. + // 1183: An implementation cannot be declared in ambient contexts. + declare declareMethod(): i32 {} } diff --git a/tests/parser/class.ts.fixture.ts b/tests/parser/class.ts.fixture.ts index dfdd064c5b..2b114d0904 100644 --- a/tests/parser/class.ts.fixture.ts +++ b/tests/parser/class.ts.fixture.ts @@ -8,18 +8,24 @@ export class Valid { static staticField: i32; static void: i32; void: i32 = Valid.void; + declare declareField: i32; } export class Invalid { constructor() {} instanceFunction() {} get instanceGetter(a: i32) {} set instanceSetter() {} + declare declareInitializer: i32 = 1; + declare declareMethod(): i32 {} } -// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts(15,14+3) -// ERROR 1110: "Type expected." in class.ts(18,21+0) -// ERROR 1094: "An accessor cannot have type parameters." in class.ts(23,21+3) -// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts(23,7+14) -// ERROR 1110: "Type expected." in class.ts(23,32+0) -// ERROR 1094: "An accessor cannot have type parameters." in class.ts(28,21+3) -// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts(28,7+14) -// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts(28,26+1) +// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts(16,14+3) +// ERROR 1110: "Type expected." in class.ts(19,21+0) +// ERROR 1094: "An accessor cannot have type parameters." in class.ts(24,21+3) +// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts(24,7+14) +// ERROR 1110: "Type expected." in class.ts(24,32+0) +// ERROR 1094: "An accessor cannot have type parameters." in class.ts(29,21+3) +// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts(29,7+14) +// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts(29,26+1) +// ERROR 1039: "Initializers are not allowed in ambient contexts." in class.ts(31,35+1) +// ERROR 1042: "'declare' modifier cannot be used here." in class.ts(32,3+7) +// ERROR 1183: "An implementation cannot be declared in ambient contexts." in class.ts(32,32+1) From 10272dea4d8aa03e5f8543578036584abbd3806e Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 13:54:49 -0600 Subject: [PATCH 03/13] fix error lines --- tests/parser/class.ts.fixture.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/parser/class.ts.fixture.ts b/tests/parser/class.ts.fixture.ts index 2b114d0904..70c347302b 100644 --- a/tests/parser/class.ts.fixture.ts +++ b/tests/parser/class.ts.fixture.ts @@ -26,6 +26,6 @@ export class Invalid { // ERROR 1094: "An accessor cannot have type parameters." in class.ts(29,21+3) // ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts(29,7+14) // ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts(29,26+1) -// ERROR 1039: "Initializers are not allowed in ambient contexts." in class.ts(31,35+1) -// ERROR 1042: "'declare' modifier cannot be used here." in class.ts(32,3+7) -// ERROR 1183: "An implementation cannot be declared in ambient contexts." in class.ts(32,32+1) +// ERROR 1039: "Initializers are not allowed in ambient contexts." in class.ts(32,35+1) +// ERROR 1042: "'declare' modifier cannot be used here." in class.ts(36,3+7) +// ERROR 1183: "An implementation cannot be declared in ambient contexts." in class.ts(36,32+1) From 61db171aa203a083ef68e14539325e8597313c2e Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 14:05:31 -0600 Subject: [PATCH 04/13] fix `declare` as identifier --- src/parser.ts | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index 07eb01fcee..03c239f03c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1874,25 +1874,32 @@ export class Parser extends DiagnosticEmitter { var declareStart = 0; var declareEnd = 0; var contextIsAmbient = parent.is(CommonFlags.AMBIENT); - if (tn.skip(Token.DECLARE)) { - if (isInterface) { - this.error( - DiagnosticCode._0_modifier_cannot_be_used_here, - tn.range(), "declare" - ); - } else { - if (contextIsAmbient) { + if (tn.peek() == Token.DECLARE) { + let state = tn.mark(); + tn.next(); + if (tn.peek() != Token.COLON) { // modifier + tn.discard(state); + if (isInterface) { this.error( - DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context, - tn.range() - ); // recoverable + DiagnosticCode._0_modifier_cannot_be_used_here, + tn.range(), "declare" + ); } else { - flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT; - declareStart = tn.tokenPos; - declareEnd = tn.pos; + if (contextIsAmbient) { + this.error( + DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context, + tn.range() + ); // recoverable + } else { + flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT; + declareStart = tn.tokenPos; + declareEnd = tn.pos; + } } + if (!startPos) startPos = tn.tokenPos; + } else { // identifier + tn.reset(state); } - if (!startPos) startPos = tn.tokenPos; } else if (contextIsAmbient) { flags |= CommonFlags.AMBIENT; } From 34ecdfd38b61adb8402a832a0cbf0b87dceef755 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 14:15:15 -0600 Subject: [PATCH 05/13] fix --- src/resolver.ts | 54 +++++++++++----------- tests/compiler/duplicate-field-errors.json | 9 ++-- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index 1e4ddc2552..010e5c8081 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3099,30 +3099,6 @@ export class Resolver extends DiagnosticEmitter { let baseField = assert(baseMembers.get(fieldPrototype.name)); assert(baseField.kind == ElementKind.FIELD); existingField = baseField; - - // visibility checks - let thisFieldIsPublic = fieldPrototype.isPublic; - let existingFieldIsPublic = existingField.isPublic; - - if (thisFieldIsPublic && !existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, base.internalName, instance.internalName - ); - } else if (!thisFieldIsPublic && existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, instance.internalName, base.internalName - ); - } else if (!thisFieldIsPublic && !existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Types_have_separate_declarations_of_a_private_property_0, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name - ); - } } } if (!fieldTypeNode) { @@ -3156,18 +3132,42 @@ export class Resolver extends DiagnosticEmitter { } if (!fieldType) break; // did report above if (existingField !== null) { + // visibility checks + let thisFieldIsPublic = fieldPrototype.isPublic; + let existingFieldIsPublic = existingField.isPublic; + let baseClass = base; + + if (thisFieldIsPublic && !existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, baseClass.internalName, instance.internalName + ); + } else if (!thisFieldIsPublic && existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, instance.internalName, baseClass.internalName + ); + } else if (!thisFieldIsPublic && !existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Types_have_separate_declarations_of_a_private_property_0, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name + ); + } // assignability checks - if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null && !fieldPrototype.is(CommonFlags.DECLARE)) { + else if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null && !fieldPrototype.is(CommonFlags.DECLARE)) { this.errorRelated( DiagnosticCode.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration, fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, assert(base).internalName + fieldPrototype.name, baseClass.internalName ); } else if (!fieldType.isStrictlyAssignableTo(existingField.type)) { this.errorRelated( DiagnosticCode.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, instance.internalName, assert(base).internalName + fieldPrototype.name, instance.internalName, baseClass.internalName ); } } diff --git a/tests/compiler/duplicate-field-errors.json b/tests/compiler/duplicate-field-errors.json index d0afa77c37..4f53f1fe62 100644 --- a/tests/compiler/duplicate-field-errors.json +++ b/tests/compiler/duplicate-field-errors.json @@ -2,9 +2,10 @@ "asc_flags": [ ], "stderr": [ - "TS2325: Property 'foo' is private in type 'duplicate-field-errors/A' but not in type 'duplicate-field-errors/B'.", - "TS2325: Property 'bar' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", - "TS2442: Types have separate declarations of a private property 'baz'.", - "TS2416: Property 'raz' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'." + "TS2325: Property 'a' is private in type 'duplicate-field-errors/A' but not in type 'duplicate-field-errors/B'.", + "TS2325: Property 'b' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", + "TS2442: Types have separate declarations of a private property 'c'.", + "TS2416: Property 'd' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'.", + "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration." ] } From ea6705a8f5ff76439f24820d22c2081598ef88a4 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 19:11:50 -0600 Subject: [PATCH 06/13] patch non-field base member crash --- src/resolver.ts | 12 ++++++++++-- tests/compiler/duplicate-field-errors.json | 4 +++- tests/compiler/duplicate-field-errors.ts | 6 +++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index 010e5c8081..e7c2000380 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3097,8 +3097,16 @@ export class Resolver extends DiagnosticEmitter { let baseMembers = base.members; if (baseMembers !== null && baseMembers.has(fieldPrototype.name)) { let baseField = assert(baseMembers.get(fieldPrototype.name)); - assert(baseField.kind == ElementKind.FIELD); - existingField = baseField; + if (baseField.kind == ElementKind.FIELD) { + existingField = baseField; + } else { + this.errorRelated( + DiagnosticCode.Duplicate_identifier_0, + fieldPrototype.identifierNode.range, baseField.identifierNode.range, + fieldPrototype.name + ); + break; + } } } if (!fieldTypeNode) { diff --git a/tests/compiler/duplicate-field-errors.json b/tests/compiler/duplicate-field-errors.json index 4f53f1fe62..7266f768fc 100644 --- a/tests/compiler/duplicate-field-errors.json +++ b/tests/compiler/duplicate-field-errors.json @@ -6,6 +6,8 @@ "TS2325: Property 'b' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", "TS2442: Types have separate declarations of a private property 'c'.", "TS2416: Property 'd' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'.", - "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration." + "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.", + "TS2300: Duplicate identifier 'f'.", + "EOF" ] } diff --git a/tests/compiler/duplicate-field-errors.ts b/tests/compiler/duplicate-field-errors.ts index 19f9379d9d..505dce7dfe 100644 --- a/tests/compiler/duplicate-field-errors.ts +++ b/tests/compiler/duplicate-field-errors.ts @@ -11,6 +11,7 @@ class A { this.d = d; this.e = e; } + f(): void {} } export class B extends A { @@ -19,8 +20,11 @@ export class B extends A { private c: i32; public d: i32; public e: i32; - constructor(a: i32, b: i32, c: i32, d: i32, e: i32) { + public f: i32; + constructor(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { super(a, b, c, d, e); + ERROR("EOF"); } } + From 893e0527bfa881a3b2983a1debb547223aec494a Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 19:18:23 -0600 Subject: [PATCH 07/13] revise tests to ensure existing memory offset use --- src/resolver.ts | 13 ++-- tests/compiler/duplicate-fields.optimized.wat | 69 ++++++++--------- tests/compiler/duplicate-fields.ts | 7 +- tests/compiler/duplicate-fields.untouched.wat | 76 ++++++++++--------- 4 files changed, 86 insertions(+), 79 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index e7c2000380..55f984d536 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3105,7 +3105,6 @@ export class Resolver extends DiagnosticEmitter { fieldPrototype.identifierNode.range, baseField.identifierNode.range, fieldPrototype.name ); - break; } } } @@ -3181,10 +3180,14 @@ export class Resolver extends DiagnosticEmitter { } let fieldInstance = new Field(fieldPrototype, instance, fieldType); assert(isPowerOf2(fieldType.byteSize)); - let mask = fieldType.byteSize - 1; - if (memoryOffset & mask) memoryOffset = (memoryOffset | mask) + 1; - fieldInstance.memoryOffset = memoryOffset; - memoryOffset += fieldType.byteSize; + if (existingField !== null) { + fieldInstance.memoryOffset = existingField.memoryOffset; + } else { + let mask = fieldType.byteSize - 1; + if (memoryOffset & mask) memoryOffset = (memoryOffset | mask) + 1; + fieldInstance.memoryOffset = memoryOffset; + memoryOffset += fieldType.byteSize; + } instance.add(memberName, fieldInstance); // reports break; } diff --git a/tests/compiler/duplicate-fields.optimized.wat b/tests/compiler/duplicate-fields.optimized.wat index b66877028e..886ae81ee7 100644 --- a/tests/compiler/duplicate-fields.optimized.wat +++ b/tests/compiler/duplicate-fields.optimized.wat @@ -34,9 +34,9 @@ (data (i32.const 1436) "<") (data (i32.const 1448) "\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s") (data (i32.const 1504) "\t\00\00\00 \00\00\00\00\00\00\00 ") - (data (i32.const 1532) " \00\00\00\04\00\00\00 ") - (data (i32.const 1552) "\06") - (data (i32.const 1564) " \00\00\00\00\00\00\00 \00\00\00\07") + (data (i32.const 1532) " \00\00\00\00\00\00\00 \00\00\00\03") + (data (i32.const 1556) " ") + (data (i32.const 1568) "\05\00\00\00 \00\00\00\06") (export "memory" (memory $0)) (start $~start) (func $~lib/rt/itcms/visitRoots @@ -1775,17 +1775,17 @@ block $folding-inner0 block $invalid block $duplicate-fields/Bar - block $duplicate-fields/Foo - block $duplicate-fields/B2 - block $duplicate-fields/A - block $duplicate-fields/B + block $duplicate-fields/B2 + block $duplicate-fields/Foo + block $duplicate-fields/B + block $duplicate-fields/A block $~lib/string/String block $~lib/arraybuffer/ArrayBuffer local.get $0 i32.const 8 i32.sub i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/B $duplicate-fields/A $duplicate-fields/B2 $folding-inner0 $duplicate-fields/Foo $duplicate-fields/Bar $invalid + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/A $duplicate-fields/B $folding-inner0 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $invalid end return end @@ -1795,23 +1795,16 @@ end return end - local.get $0 - i32.load - local.tee $1 - if - local.get $1 - call $~lib/rt/itcms/__visit - end - local.get $0 - i32.load offset=4 - local.tee $0 - if - local.get $0 - call $~lib/rt/itcms/__visit - end return end - return + local.get $0 + i32.load + local.tee $1 + if + local.get $1 + call $~lib/rt/itcms/__visit + end + br $folding-inner0 end return end @@ -1887,14 +1880,14 @@ i32.const 0 i32.store local.get $0 - i32.const 8 - i32.const 3 + i32.const 4 + i32.const 4 call $~lib/rt/itcms/__new local.tee $0 i32.store local.get $0 i32.const 0 - i32.store offset=4 + i32.store global.get $~lib/memory/__stack_pointer local.tee $1 i32.const 4 @@ -1912,7 +1905,7 @@ if global.get $~lib/memory/__stack_pointer i32.const 4 - i32.const 4 + i32.const 3 call $~lib/rt/itcms/__new local.tee $0 i32.store @@ -1932,7 +1925,7 @@ i32.store local.get $0 i32.const 10 - i32.store offset=4 + i32.store global.get $~lib/memory/__stack_pointer i32.const 4 i32.add @@ -1940,13 +1933,13 @@ local.get $0 global.set $duplicate-fields/foo global.get $duplicate-fields/foo - i32.load offset=4 + i32.load i32.const 10 i32.ne if i32.const 0 i32.const 1456 - i32.const 13 + i32.const 15 i32.const 1 call $~lib/builtins/abort unreachable @@ -1989,7 +1982,7 @@ if global.get $~lib/memory/__stack_pointer i32.const 4 - i32.const 7 + i32.const 6 call $~lib/rt/itcms/__new local.tee $1 i32.store @@ -2030,14 +2023,14 @@ i32.const 0 i32.store local.get $0 - i32.const 8 - i32.const 5 + i32.const 4 + i32.const 7 call $~lib/rt/itcms/__new local.tee $0 i32.store local.get $0 i32.const 0 - i32.store offset=4 + i32.store local.get $0 i32.const 0 call $~lib/rt/itcms/__link @@ -2058,7 +2051,7 @@ if global.get $~lib/memory/__stack_pointer i32.const 4 - i32.const 6 + i32.const 5 call $~lib/rt/itcms/__new local.tee $0 i32.store @@ -2084,7 +2077,7 @@ i32.store local.get $0 local.get $1 - i32.store offset=4 + i32.store local.get $0 local.get $1 call $~lib/rt/itcms/__link @@ -2095,14 +2088,14 @@ local.get $0 global.set $duplicate-fields/raz global.get $duplicate-fields/raz - i32.load offset=4 + i32.load i32.load offset=4 i32.const 2 i32.ne if i32.const 0 i32.const 1456 - i32.const 40 + i32.const 43 i32.const 1 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/duplicate-fields.ts b/tests/compiler/duplicate-fields.ts index 1fa31dde5e..5c4e018ebb 100644 --- a/tests/compiler/duplicate-fields.ts +++ b/tests/compiler/duplicate-fields.ts @@ -8,7 +8,9 @@ class B extends A { constructor(bar: i32) { super(bar); this.bar = bar; } } -assert(sizeof() == sizeof()); +assert(offsetof("bar") == 0); +assert(offsetof("bar") == 0); + const foo = new B(10); assert(foo.bar == 10); @@ -34,7 +36,8 @@ class B2 extends A2 { constructor(bar: Bar) { super(bar); this.bar = bar; } } +assert(offsetof("bar") == 0); +assert(offsetof("bar") == 0); -assert(sizeof() == sizeof()); const raz = new B2(new Bar(1, 2)); assert(raz.bar.bar == 2); \ No newline at end of file diff --git a/tests/compiler/duplicate-fields.untouched.wat b/tests/compiler/duplicate-fields.untouched.wat index db15d779b5..514f60695e 100644 --- a/tests/compiler/duplicate-fields.untouched.wat +++ b/tests/compiler/duplicate-fields.untouched.wat @@ -40,7 +40,7 @@ (data (i32.const 320) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 348) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 412) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s\00\00\00\00\00\00\00") - (data (i32.const 480) "\t\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\04\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\06\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\07\00\00\00") + (data (i32.const 480) "\t\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\03\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\05\00\00\00 \00\00\00\06\00\00\00") (table $0 1 funcref) (elem $0 (i32.const 1)) (export "memory" (memory $0)) @@ -2356,7 +2356,7 @@ (func $duplicate-fields/B#set:bar (param $0 i32) (param $1 i32) local.get $0 local.get $1 - i32.store offset=4 + i32.store ) (func $~lib/rt/itcms/__link (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) @@ -2438,7 +2438,7 @@ (func $duplicate-fields/B2#set:bar (param $0 i32) (param $1 i32) local.get $0 local.get $1 - i32.store offset=4 + i32.store local.get $0 local.get $1 i32.const 0 @@ -2488,13 +2488,10 @@ call $~lib/rt/itcms/__visit end ) - (func $duplicate-fields/B2~visit (param $0 i32) (param $1 i32) + (func $duplicate-fields/A2~visit (param $0 i32) (param $1 i32) (local $2 i32) local.get $0 - local.get $1 - call $duplicate-fields/A2~visit - local.get $0 - i32.load offset=4 + i32.load local.tee $2 if local.get $2 @@ -2502,9 +2499,12 @@ call $~lib/rt/itcms/__visit end ) - (func $duplicate-fields/A2~visit (param $0 i32) (param $1 i32) + (func $duplicate-fields/B2~visit (param $0 i32) (param $1 i32) (local $2 i32) local.get $0 + local.get $1 + call $duplicate-fields/A2~visit + local.get $0 i32.load local.tee $2 if @@ -2516,11 +2516,11 @@ (func $~lib/rt/__visit_members (param $0 i32) (param $1 i32) block $invalid block $duplicate-fields/Bar - block $duplicate-fields/Foo - block $duplicate-fields/A2 - block $duplicate-fields/B2 - block $duplicate-fields/A - block $duplicate-fields/B + block $duplicate-fields/B2 + block $duplicate-fields/Foo + block $duplicate-fields/A2 + block $duplicate-fields/B + block $duplicate-fields/A block $~lib/arraybuffer/ArrayBufferView block $~lib/string/String block $~lib/arraybuffer/ArrayBuffer @@ -2528,7 +2528,7 @@ i32.const 8 i32.sub i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $duplicate-fields/B $duplicate-fields/A $duplicate-fields/B2 $duplicate-fields/A2 $duplicate-fields/Foo $duplicate-fields/Bar $invalid + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $duplicate-fields/A $duplicate-fields/B $duplicate-fields/A2 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $invalid end return end @@ -2545,14 +2545,14 @@ end local.get $0 local.get $1 - call $duplicate-fields/B2~visit + call $duplicate-fields/A2~visit return end - local.get $0 - local.get $1 - call $duplicate-fields/A2~visit return end + local.get $0 + local.get $1 + call $duplicate-fields/B2~visit return end return @@ -2585,8 +2585,12 @@ global.get $~lib/memory/__stack_pointer i32.const 0 i32.store - i32.const 4 - i32.const 4 + i32.const 0 + i32.const 0 + i32.eq + drop + i32.const 0 + i32.const 0 i32.eq drop memory.size @@ -2611,20 +2615,24 @@ call $duplicate-fields/B#constructor global.set $duplicate-fields/foo global.get $duplicate-fields/foo - i32.load offset=4 + i32.load i32.const 10 i32.eq i32.eqz if i32.const 0 i32.const 432 - i32.const 13 + i32.const 15 i32.const 1 call $~lib/builtins/abort unreachable end - i32.const 4 - i32.const 4 + i32.const 0 + i32.const 0 + i32.eq + drop + i32.const 0 + i32.const 0 i32.eq drop i32.const 0 @@ -2640,7 +2648,7 @@ call $duplicate-fields/B2#constructor global.set $duplicate-fields/raz global.get $duplicate-fields/raz - i32.load offset=4 + i32.load i32.load offset=4 i32.const 2 i32.eq @@ -2648,7 +2656,7 @@ if i32.const 0 i32.const 432 - i32.const 40 + i32.const 43 i32.const 1 call $~lib/builtins/abort unreachable @@ -2673,7 +2681,7 @@ if global.get $~lib/memory/__stack_pointer i32.const 4 - i32.const 4 + i32.const 3 call $~lib/rt/itcms/__new local.tee $0 i32.store @@ -2706,8 +2714,8 @@ i32.eqz if global.get $~lib/memory/__stack_pointer - i32.const 8 - i32.const 3 + i32.const 4 + i32.const 4 call $~lib/rt/itcms/__new local.tee $0 i32.store @@ -2747,7 +2755,7 @@ if global.get $~lib/memory/__stack_pointer i32.const 4 - i32.const 6 + i32.const 5 call $~lib/rt/itcms/__new local.tee $0 i32.store @@ -2780,8 +2788,8 @@ i32.eqz if global.get $~lib/memory/__stack_pointer - i32.const 8 - i32.const 5 + i32.const 4 + i32.const 7 call $~lib/rt/itcms/__new local.tee $0 i32.store @@ -2821,7 +2829,7 @@ if global.get $~lib/memory/__stack_pointer i32.const 4 - i32.const 7 + i32.const 6 call $~lib/rt/itcms/__new local.tee $0 i32.store From 0bd2c801c56ed476fa5933813b73da26e3ff84a3 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 19:25:42 -0600 Subject: [PATCH 08/13] remove `declare` for fields --- src/diagnosticMessages.generated.ts | 4 +-- src/diagnosticMessages.json | 2 +- src/parser.ts | 47 ----------------------------- src/resolver.ts | 4 +-- tests/parser/class.ts | 8 ----- tests/parser/class.ts.fixture.ts | 22 +++++--------- 6 files changed, 13 insertions(+), 74 deletions(-) diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index b52aeee707..602e7e0525 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -173,7 +173,7 @@ export enum DiagnosticCode { Expected_0_type_arguments_but_got_1 = 2558, Property_0_has_no_initializer_and_is_not_assigned_in_the_constructor_before_this_is_used_or_returned = 2564, Property_0_is_used_before_being_assigned = 2565, - Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration = 2612, + Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_remove_the_redundant_declaration = 2612, A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums = 2651, Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration = 2673, Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration = 2674, @@ -361,7 +361,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2558: return "Expected {0} type arguments, but got {1}."; case 2564: return "Property '{0}' has no initializer and is not assigned in the constructor before 'this' is used or returned."; case 2565: return "Property '{0}' is used before being assigned."; - case 2612: return "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration."; + case 2612: return "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration."; case 2651: return "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums."; case 2673: return "Constructor of class '{0}' is private and only accessible within the class declaration."; case 2674: return "Constructor of class '{0}' is protected and only accessible within the class declaration."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 9952871646..1dd4687737 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -171,7 +171,7 @@ "Expected {0} type arguments, but got {1}.": 2558, "Property '{0}' has no initializer and is not assigned in the constructor before 'this' is used or returned.": 2564, "Property '{0}' is used before being assigned.": 2565, - "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.": 2612, + "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration.": 2612, "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": 2651, "Constructor of class '{0}' is private and only accessible within the class declaration.": 2673, "Constructor of class '{0}' is protected and only accessible within the class declaration.": 2674, diff --git a/src/parser.ts b/src/parser.ts index 03c239f03c..7ef8c4891c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1839,7 +1839,6 @@ export class Parser extends DiagnosticEmitter { ): Node | null { // before: - // 'declare'? // ('public' | 'private' | 'protected')? // ('static' | 'abstract')? // 'readonly'? @@ -1871,39 +1870,6 @@ export class Parser extends DiagnosticEmitter { // implemented methods are virtual if (isInterface) flags |= CommonFlags.VIRTUAL; - var declareStart = 0; - var declareEnd = 0; - var contextIsAmbient = parent.is(CommonFlags.AMBIENT); - if (tn.peek() == Token.DECLARE) { - let state = tn.mark(); - tn.next(); - if (tn.peek() != Token.COLON) { // modifier - tn.discard(state); - if (isInterface) { - this.error( - DiagnosticCode._0_modifier_cannot_be_used_here, - tn.range(), "declare" - ); - } else { - if (contextIsAmbient) { - this.error( - DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context, - tn.range() - ); // recoverable - } else { - flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT; - declareStart = tn.tokenPos; - declareEnd = tn.pos; - } - } - if (!startPos) startPos = tn.tokenPos; - } else { // identifier - tn.reset(state); - } - } else if (contextIsAmbient) { - flags |= CommonFlags.AMBIENT; - } - var accessStart = 0; var accessEnd = 0; if (tn.skip(Token.PUBLIC)) { @@ -2033,12 +1999,6 @@ export class Parser extends DiagnosticEmitter { tn.range(readonlyStart, readonlyEnd), "readonly" ); // recoverable } - if (flags & CommonFlags.DECLARE) { - this.error( - DiagnosticCode._0_modifier_cannot_be_used_here, - tn.range(declareStart, declareEnd), "declare" - ); // recoverable - } } else { tn.reset(state); } @@ -2148,13 +2108,6 @@ export class Parser extends DiagnosticEmitter { // method: '(' Parameters (':' Type)? '{' Statement* '}' ';'? if (tn.skip(Token.OPENPAREN)) { - if (flags & CommonFlags.DECLARE) { - this.error( - DiagnosticCode._0_modifier_cannot_be_used_here, - tn.range(declareStart, declareEnd), "declare" - ); // recoverable - } - let signatureStart = tn.tokenPos; let parameters = this.parseParameters(tn, isConstructor); if (!parameters) return null; diff --git a/src/resolver.ts b/src/resolver.ts index 55f984d536..5e9503f722 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3164,9 +3164,9 @@ export class Resolver extends DiagnosticEmitter { ); } // assignability checks - else if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null && !fieldPrototype.is(CommonFlags.DECLARE)) { + else if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null) { this.errorRelated( - DiagnosticCode.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration, + DiagnosticCode.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_remove_the_redundant_declaration, fieldPrototype.identifierNode.range, existingField.identifierNode.range, fieldPrototype.name, baseClass.internalName ); diff --git a/tests/parser/class.ts b/tests/parser/class.ts index 20470aa0aa..e80a34b527 100644 --- a/tests/parser/class.ts +++ b/tests/parser/class.ts @@ -8,7 +8,6 @@ export class Valid { static staticField: i32; static void: i32; void: i32 = Valid.void; - declare declareField: i32; } export class Invalid { @@ -27,11 +26,4 @@ export class Invalid { // 1049: A 'set' accessor must have exactly one parameter. // 1095: A 'set' accessor cannot have a return type annotation. set instanceSetter(): i32 {} - - // 1039: Initializers are not allowed in ambient contexts. - declare declareInitializer: i32 = 1; - - // 1042: 'declare' modifier cannot be used here. - // 1183: An implementation cannot be declared in ambient contexts. - declare declareMethod(): i32 {} } diff --git a/tests/parser/class.ts.fixture.ts b/tests/parser/class.ts.fixture.ts index 70c347302b..dfdd064c5b 100644 --- a/tests/parser/class.ts.fixture.ts +++ b/tests/parser/class.ts.fixture.ts @@ -8,24 +8,18 @@ export class Valid { static staticField: i32; static void: i32; void: i32 = Valid.void; - declare declareField: i32; } export class Invalid { constructor() {} instanceFunction() {} get instanceGetter(a: i32) {} set instanceSetter() {} - declare declareInitializer: i32 = 1; - declare declareMethod(): i32 {} } -// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts(16,14+3) -// ERROR 1110: "Type expected." in class.ts(19,21+0) -// ERROR 1094: "An accessor cannot have type parameters." in class.ts(24,21+3) -// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts(24,7+14) -// ERROR 1110: "Type expected." in class.ts(24,32+0) -// ERROR 1094: "An accessor cannot have type parameters." in class.ts(29,21+3) -// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts(29,7+14) -// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts(29,26+1) -// ERROR 1039: "Initializers are not allowed in ambient contexts." in class.ts(32,35+1) -// ERROR 1042: "'declare' modifier cannot be used here." in class.ts(36,3+7) -// ERROR 1183: "An implementation cannot be declared in ambient contexts." in class.ts(36,32+1) +// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts(15,14+3) +// ERROR 1110: "Type expected." in class.ts(18,21+0) +// ERROR 1094: "An accessor cannot have type parameters." in class.ts(23,21+3) +// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts(23,7+14) +// ERROR 1110: "Type expected." in class.ts(23,32+0) +// ERROR 1094: "An accessor cannot have type parameters." in class.ts(28,21+3) +// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts(28,7+14) +// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts(28,26+1) From d3ed92066d62c061adc616ea873173a641479741 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 19:30:47 -0600 Subject: [PATCH 09/13] more --- src/extra/ast.ts | 3 --- src/parser.ts | 6 ------ 2 files changed, 9 deletions(-) diff --git a/src/extra/ast.ts b/src/extra/ast.ts index cbffac40fb..ffa272d1a8 100644 --- a/src/extra/ast.ts +++ b/src/extra/ast.ts @@ -1677,9 +1677,6 @@ export class ASTBuilder { serializeAccessModifiers(node: DeclarationStatement): void { var sb = this.sb; - if (node.is(CommonFlags.DECLARE)) { - sb.push("declare "); - } if (node.is(CommonFlags.PUBLIC)) { sb.push("public "); } else if (node.is(CommonFlags.PRIVATE)) { diff --git a/src/parser.ts b/src/parser.ts index 7ef8c4891c..53bbdd0562 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -2291,12 +2291,6 @@ export class Parser extends DiagnosticEmitter { } let initializer: Expression | null = null; if (tn.skip(Token.EQUALS)) { - if (flags & CommonFlags.AMBIENT) { - this.error( - DiagnosticCode.Initializers_are_not_allowed_in_ambient_contexts, - tn.range() - ); // recoverable - } initializer = this.parseExpression(tn); if (!initializer) return null; } From 0d27e0ef20af52a6c1b80a6086ede6cbc725acae Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Sun, 28 Nov 2021 19:36:01 -0600 Subject: [PATCH 10/13] fix tests --- tests/compiler/duplicate-field-errors.json | 2 +- tests/compiler/duplicate-fields.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/compiler/duplicate-field-errors.json b/tests/compiler/duplicate-field-errors.json index 7266f768fc..61ad2da9d0 100644 --- a/tests/compiler/duplicate-field-errors.json +++ b/tests/compiler/duplicate-field-errors.json @@ -6,7 +6,7 @@ "TS2325: Property 'b' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", "TS2442: Types have separate declarations of a private property 'c'.", "TS2416: Property 'd' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'.", - "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.", + "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration.", "TS2300: Duplicate identifier 'f'.", "EOF" ] diff --git a/tests/compiler/duplicate-fields.ts b/tests/compiler/duplicate-fields.ts index 5c4e018ebb..fea597d333 100644 --- a/tests/compiler/duplicate-fields.ts +++ b/tests/compiler/duplicate-fields.ts @@ -4,7 +4,7 @@ class A { } class B extends A { - declare bar: i32; + bar: i32 = 0; constructor(bar: i32) { super(bar); this.bar = bar; } } From 96fbcf5a1cb81f219019dd8b1855bfa9412a4fcf Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Tue, 30 Nov 2021 21:43:35 -0600 Subject: [PATCH 11/13] handle protected fields --- src/diagnosticMessages.generated.ts | 2 ++ src/diagnosticMessages.json | 1 + src/resolver.ts | 16 +++++++++++----- tests/compiler/duplicate-field-errors.json | 3 ++- tests/compiler/duplicate-field-errors.ts | 11 +++++++---- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 602e7e0525..1afa167a39 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -153,6 +153,7 @@ export enum DiagnosticCode { A_class_can_only_implement_an_interface = 2422, A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged = 2434, Types_have_separate_declarations_of_a_private_property_0 = 2442, + Property_0_is_protected_in_type_1_but_public_in_type_2 = 2444, Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses = 2445, Variable_0_used_before_its_declaration = 2448, Cannot_redeclare_block_scoped_variable_0 = 2451, @@ -341,6 +342,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2422: return "A class can only implement an interface."; case 2434: return "A namespace declaration cannot be located prior to a class or function with which it is merged."; case 2442: return "Types have separate declarations of a private property '{0}'."; + case 2444: return "Property '{0}' is protected in type '{1}' but public in type '{2}'."; case 2445: return "Property '{0}' is protected and only accessible within class '{1}' and its subclasses."; case 2448: return "Variable '{0}' used before its declaration."; case 2451: return "Cannot redeclare block-scoped variable '{0}'"; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 1dd4687737..787dcdf432 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -151,6 +151,7 @@ "A class can only implement an interface.": 2422, "A namespace declaration cannot be located prior to a class or function with which it is merged.": 2434, "Types have separate declarations of a private property '{0}'.": 2442, + "Property '{0}' is protected in type '{1}' but public in type '{2}'.": 2444, "Property '{0}' is protected and only accessible within class '{1}' and its subclasses.": 2445, "Variable '{0}' used before its declaration.": 2448, "Cannot redeclare block-scoped variable '{0}'" : 2451, diff --git a/src/resolver.ts b/src/resolver.ts index 5e9503f722..71305d4b2c 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3140,23 +3140,29 @@ export class Resolver extends DiagnosticEmitter { if (!fieldType) break; // did report above if (existingField !== null) { // visibility checks - let thisFieldIsPublic = fieldPrototype.isPublic; - let existingFieldIsPublic = existingField.isPublic; let baseClass = base; + let thisFieldIsPubOrProt = !fieldPrototype.is(CommonFlags.PRIVATE); + let existingFieldIsPublic = existingField.isPublic; - if (thisFieldIsPublic && !existingFieldIsPublic) { + if (thisFieldIsPubOrProt && !existingFieldIsPublic) { this.errorRelated( DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, fieldPrototype.identifierNode.range, existingField.identifierNode.range, fieldPrototype.name, baseClass.internalName, instance.internalName ); - } else if (!thisFieldIsPublic && existingFieldIsPublic) { + } else if (fieldPrototype.is(CommonFlags.PROTECTED) && existingFieldIsPublic) { + this.errorRelated( + DiagnosticCode.Property_0_is_protected_in_type_1_but_public_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, instance.internalName, baseClass.internalName + ); + } else if (!thisFieldIsPubOrProt && existingFieldIsPublic) { this.errorRelated( DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, fieldPrototype.identifierNode.range, existingField.identifierNode.range, fieldPrototype.name, instance.internalName, baseClass.internalName ); - } else if (!thisFieldIsPublic && !existingFieldIsPublic) { + } else if (!thisFieldIsPubOrProt && !existingFieldIsPublic) { this.errorRelated( DiagnosticCode.Types_have_separate_declarations_of_a_private_property_0, fieldPrototype.identifierNode.range, existingField.identifierNode.range, diff --git a/tests/compiler/duplicate-field-errors.json b/tests/compiler/duplicate-field-errors.json index 61ad2da9d0..eff1f143f9 100644 --- a/tests/compiler/duplicate-field-errors.json +++ b/tests/compiler/duplicate-field-errors.json @@ -7,7 +7,8 @@ "TS2442: Types have separate declarations of a private property 'c'.", "TS2416: Property 'd' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'.", "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration.", - "TS2300: Duplicate identifier 'f'.", + "TS2300: Duplicate identifier 'g'.", + "TS2444: Property 'f' is protected in type 'duplicate-field-errors/B' but public in type 'duplicate-field-errors/A'.", "EOF" ] } diff --git a/tests/compiler/duplicate-field-errors.ts b/tests/compiler/duplicate-field-errors.ts index 505dce7dfe..bd2f1601a1 100644 --- a/tests/compiler/duplicate-field-errors.ts +++ b/tests/compiler/duplicate-field-errors.ts @@ -4,14 +4,16 @@ class A { private c: i32; public d: i64; public e: i32; - constructor(a: i32, b: i32, c: i32, d: i64, e: i32) { + public f: i32; + constructor(a: i32, b: i32, c: i32, d: i64, e: i32, f: i32) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; + this.f = f; } - f(): void {} + g(): void {} } export class B extends A { @@ -20,9 +22,10 @@ export class B extends A { private c: i32; public d: i32; public e: i32; - public f: i32; + public g: i32; + protected f: i32; constructor(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { - super(a, b, c, d, e); + super(a, b, c, d, e, f); ERROR("EOF"); } } From d8828779c5bdf10ea605e49f0011f2a126e32f98 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Tue, 30 Nov 2021 23:27:55 -0600 Subject: [PATCH 12/13] revise visibility checks --- src/resolver.ts | 83 +++-- tests/compiler/duplicate-fields.optimized.wat | 287 +++++++++++++++--- tests/compiler/duplicate-fields.ts | 15 +- tests/compiler/duplicate-fields.untouched.wat | 250 +++++++++++++-- 4 files changed, 535 insertions(+), 100 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index 71305d4b2c..e5dafb3d03 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3140,37 +3140,64 @@ export class Resolver extends DiagnosticEmitter { if (!fieldType) break; // did report above if (existingField !== null) { // visibility checks + /* + existingField visibility on top + +==================+=========+===========+=========+ + | Visibility Table | Private | Protected | Public | + +==================+=========+===========+=========+ + | Private | error | error | error | + +------------------+---------+-----------+---------+ + | Protected | error | allowed | error | + +------------------+---------+-----------+---------+ + | Public | error | allowed | allowed | + +------------------+---------+-----------+---------+ + */ + let baseClass = base; - let thisFieldIsPubOrProt = !fieldPrototype.is(CommonFlags.PRIVATE); - let existingFieldIsPublic = existingField.isPublic; - if (thisFieldIsPubOrProt && !existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, baseClass.internalName, instance.internalName - ); - } else if (fieldPrototype.is(CommonFlags.PROTECTED) && existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Property_0_is_protected_in_type_1_but_public_in_type_2, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, instance.internalName, baseClass.internalName - ); - } else if (!thisFieldIsPubOrProt && existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, instance.internalName, baseClass.internalName - ); - } else if (!thisFieldIsPubOrProt && !existingFieldIsPublic) { - this.errorRelated( - DiagnosticCode.Types_have_separate_declarations_of_a_private_property_0, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name - ); - } + // handle cases row-by-row + if (fieldPrototype.is(CommonFlags.PRIVATE)) { + if (existingField.is(CommonFlags.PRIVATE)) { + this.errorRelated( + DiagnosticCode.Types_have_separate_declarations_of_a_private_property_0, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name + ); + } else { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, instance.internalName, baseClass.internalName + ); + } + } else if (fieldPrototype.is(CommonFlags.PROTECTED)) { + if (existingField.is(CommonFlags.PRIVATE)) { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, baseClass.internalName, instance.internalName + ); + } else if (!existingField.is(CommonFlags.PROTECTED)) { + // may be implicitly public + this.errorRelated( + DiagnosticCode.Property_0_is_protected_in_type_1_but_public_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, instance.internalName, baseClass.internalName + ); + } + } else { + // fieldPrototype is public here + if (existingField.is(CommonFlags.PRIVATE)) { + this.errorRelated( + DiagnosticCode.Property_0_is_private_in_type_1_but_not_in_type_2, + fieldPrototype.identifierNode.range, existingField.identifierNode.range, + fieldPrototype.name, baseClass.internalName, instance.internalName + ); + } + } + // assignability checks - else if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null) { + if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null) { this.errorRelated( DiagnosticCode.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_remove_the_redundant_declaration, fieldPrototype.identifierNode.range, existingField.identifierNode.range, diff --git a/tests/compiler/duplicate-fields.optimized.wat b/tests/compiler/duplicate-fields.optimized.wat index 886ae81ee7..809ba3ce3b 100644 --- a/tests/compiler/duplicate-fields.optimized.wat +++ b/tests/compiler/duplicate-fields.optimized.wat @@ -1,11 +1,12 @@ (module - (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_none (func)) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (global $~lib/rt/itcms/total (mut i32) (i32.const 0)) (global $~lib/rt/itcms/threshold (mut i32) (i32.const 0)) @@ -19,7 +20,8 @@ (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) (global $duplicate-fields/foo (mut i32) (i32.const 0)) (global $duplicate-fields/raz (mut i32) (i32.const 0)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 17964)) + (global $duplicate-fields/B3 i32 (i32.const 9)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 17980)) (memory $0 1) (data (i32.const 1036) "<") (data (i32.const 1048) "\01\00\00\00(\00\00\00A\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e") @@ -33,11 +35,15 @@ (data (i32.const 1384) "\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s") (data (i32.const 1436) "<") (data (i32.const 1448) "\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s") - (data (i32.const 1504) "\t\00\00\00 \00\00\00\00\00\00\00 ") + (data (i32.const 1504) "\0b\00\00\00 \00\00\00\00\00\00\00 ") (data (i32.const 1532) " \00\00\00\00\00\00\00 \00\00\00\03") (data (i32.const 1556) " ") - (data (i32.const 1568) "\05\00\00\00 \00\00\00\06") + (data (i32.const 1568) "\05\00\00\00 \00\00\00\06\00\00\00\00\00\00\00\n") + (export "B3" (global $duplicate-fields/B3)) (export "memory" (memory $0)) + (export "B3#get:bar" (func $export:duplicate-fields/B3#get:bar)) + (export "B3#set:bar" (func $export:duplicate-fields/B3#set:bar)) + (export "B3#constructor" (func $export:duplicate-fields/B3#constructor)) (start $~start) (func $~lib/rt/itcms/visitRoots (local $0 i32) @@ -129,7 +135,7 @@ if i32.const 0 local.get $0 - i32.const 17964 + i32.const 17980 i32.lt_u local.get $0 i32.load offset=8 @@ -785,10 +791,10 @@ if unreachable end - i32.const 17968 + i32.const 17984 i32.const 0 i32.store - i32.const 19536 + i32.const 19552 i32.const 0 i32.store loop $for-loop|0 @@ -799,7 +805,7 @@ local.get $0 i32.const 2 i32.shl - i32.const 17968 + i32.const 17984 i32.add i32.const 0 i32.store offset=4 @@ -817,7 +823,7 @@ i32.add i32.const 2 i32.shl - i32.const 17968 + i32.const 17984 i32.add i32.const 0 i32.store offset=96 @@ -835,13 +841,13 @@ br $for-loop|0 end end - i32.const 17968 - i32.const 19540 + i32.const 17984 + i32.const 19556 memory.size i32.const 16 i32.shl call $~lib/rt/tlsf/addMemory - i32.const 17968 + i32.const 17984 global.set $~lib/rt/tlsf/ROOT ) (func $~lib/rt/itcms/step (result i32) @@ -926,7 +932,7 @@ local.set $0 loop $while-continue|0 local.get $0 - i32.const 17964 + i32.const 17980 i32.lt_u if local.get $0 @@ -1022,7 +1028,7 @@ unreachable end local.get $0 - i32.const 17964 + i32.const 17980 i32.lt_u if local.get $0 @@ -1045,7 +1051,7 @@ i32.const 4 i32.add local.tee $1 - i32.const 17964 + i32.const 17980 i32.ge_u if global.get $~lib/rt/tlsf/ROOT @@ -1770,22 +1776,41 @@ end end ) - (func $~lib/rt/__visit_members (param $0 i32) + (func $duplicate-fields/B2~visit (param $0 i32) (local $1 i32) + local.get $0 + i32.load + local.tee $1 + if + local.get $1 + call $~lib/rt/itcms/__visit + end + local.get $0 + i32.load + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + ) + (func $~lib/rt/__visit_members (param $0 i32) block $folding-inner0 block $invalid - block $duplicate-fields/Bar - block $duplicate-fields/B2 - block $duplicate-fields/Foo - block $duplicate-fields/B - block $duplicate-fields/A - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/A $duplicate-fields/B $folding-inner0 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $invalid + block $duplicate-fields/B3 + block $duplicate-fields/Bar + block $duplicate-fields/B2 + block $duplicate-fields/Foo + block $duplicate-fields/B + block $duplicate-fields/A + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/A $duplicate-fields/B $folding-inner0 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $duplicate-fields/B3 $folding-inner0 $invalid + end + return end return end @@ -1795,17 +1820,14 @@ end return end + local.get $0 + call $duplicate-fields/B2~visit return end - local.get $0 - i32.load - local.tee $1 - if - local.get $1 - call $~lib/rt/itcms/__visit - end - br $folding-inner0 + return end + local.get $0 + call $duplicate-fields/B2~visit return end unreachable @@ -1828,7 +1850,7 @@ global.set $~lib/memory/__stack_pointer block $folding-inner0 global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -1838,7 +1860,7 @@ memory.size i32.const 16 i32.shl - i32.const 17964 + i32.const 17980 i32.sub i32.const 1 i32.shr_u @@ -1872,7 +1894,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -1894,7 +1916,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -1949,7 +1971,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -1971,7 +1993,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -2015,7 +2037,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -2040,7 +2062,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 1580 + i32.const 1596 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -2106,8 +2128,181 @@ global.set $~lib/memory/__stack_pointer return end - i32.const 17984 - i32.const 18032 + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + ) + (func $export:duplicate-fields/B3#get:bar (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + if + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $1 + local.get $0 + i32.store + local.get $0 + i32.load + local.get $1 + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#set:bar (param $0 i32) (param $1 i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + if + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $2 + local.get $0 + i32.store + local.get $2 + local.get $1 + i32.store offset=4 + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.sub + global.set $~lib/memory/__stack_pointer + block $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $2 + local.get $0 + i32.store + local.get $2 + local.get $1 + i32.store offset=4 + local.get $2 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 9 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + i32.store + local.get $0 + i32.const 0 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + local.tee $2 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 10 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + i32.store + local.get $0 + i32.const 0 + call $~lib/rt/itcms/__link + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + local.get $0 + i32.store + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $0 + return + end + i32.const 18000 + i32.const 18048 i32.const 1 i32.const 1 call $~lib/builtins/abort diff --git a/tests/compiler/duplicate-fields.ts b/tests/compiler/duplicate-fields.ts index fea597d333..aba5da5e3a 100644 --- a/tests/compiler/duplicate-fields.ts +++ b/tests/compiler/duplicate-fields.ts @@ -40,4 +40,17 @@ assert(offsetof("bar") == 0); assert(offsetof("bar") == 0); const raz = new B2(new Bar(1, 2)); -assert(raz.bar.bar == 2); \ No newline at end of file +assert(raz.bar.bar == 2); + +// protected field overriding protected field shouldn't +// throw an error + +class A3 { + protected bar: Foo; + constructor(bar: Foo) { this.bar = bar; } +} + +export class B3 extends A3 { + protected bar: Bar; + constructor(bar: Bar) { super(bar); this.bar = bar; } +} \ No newline at end of file diff --git a/tests/compiler/duplicate-fields.untouched.wat b/tests/compiler/duplicate-fields.untouched.wat index 514f60695e..3be069b8ee 100644 --- a/tests/compiler/duplicate-fields.untouched.wat +++ b/tests/compiler/duplicate-fields.untouched.wat @@ -26,10 +26,11 @@ (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) (global $duplicate-fields/foo (mut i32) (i32.const 0)) (global $duplicate-fields/raz (mut i32) (i32.const 0)) + (global $duplicate-fields/B3 i32 (i32.const 9)) (global $~lib/rt/__rtti_base i32 (i32.const 480)) - (global $~lib/memory/__data_end i32 (i32.const 556)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 16940)) - (global $~lib/memory/__heap_base i32 (i32.const 16940)) + (global $~lib/memory/__data_end i32 (i32.const 572)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 16956)) + (global $~lib/memory/__heap_base i32 (i32.const 16956)) (memory $0 1) (data (i32.const 12) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00(\00\00\00A\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e\00\00\00\00\00") (data (i32.const 76) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00 \00\00\00~\00l\00i\00b\00/\00r\00t\00/\00i\00t\00c\00m\00s\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00") @@ -40,10 +41,14 @@ (data (i32.const 320) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 348) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 412) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s\00\00\00\00\00\00\00") - (data (i32.const 480) "\t\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\03\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\05\00\00\00 \00\00\00\06\00\00\00") + (data (i32.const 480) "\0b\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\03\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\05\00\00\00 \00\00\00\06\00\00\00\00\00\00\00\n\00\00\00\00\00\00\00\00\00\00\00") (table $0 1 funcref) (elem $0 (i32.const 1)) + (export "B3" (global $duplicate-fields/B3)) (export "memory" (memory $0)) + (export "B3#get:bar" (func $export:duplicate-fields/B3#get:bar)) + (export "B3#set:bar" (func $export:duplicate-fields/B3#set:bar)) + (export "B3#constructor" (func $export:duplicate-fields/B3#constructor)) (start $~start) (func $duplicate-fields/A#set:bar (param $0 i32) (param $1 i32) local.get $0 @@ -2454,6 +2459,28 @@ local.get $1 i32.store offset=4 ) + (func $duplicate-fields/A3#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + ) + (func $duplicate-fields/B3#set:bar (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + ) + (func $duplicate-fields/B3#get:bar (param $0 i32) (result i32) + local.get $0 + i32.load + ) (func $~lib/rt/__visit_globals (param $0 i32) (local $1 i32) global.get $duplicate-fields/foo @@ -2513,48 +2540,85 @@ call $~lib/rt/itcms/__visit end ) + (func $duplicate-fields/B3~visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + local.get $1 + call $duplicate-fields/A3~visit + local.get $0 + i32.load + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + ) + (func $duplicate-fields/A3~visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + ) (func $~lib/rt/__visit_members (param $0 i32) (param $1 i32) block $invalid - block $duplicate-fields/Bar - block $duplicate-fields/B2 - block $duplicate-fields/Foo - block $duplicate-fields/A2 - block $duplicate-fields/B - block $duplicate-fields/A - block $~lib/arraybuffer/ArrayBufferView - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $duplicate-fields/A $duplicate-fields/B $duplicate-fields/A2 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $invalid + block $duplicate-fields/A3 + block $duplicate-fields/B3 + block $duplicate-fields/Bar + block $duplicate-fields/B2 + block $duplicate-fields/Foo + block $duplicate-fields/A2 + block $duplicate-fields/B + block $duplicate-fields/A + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $duplicate-fields/A $duplicate-fields/B $duplicate-fields/A2 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $duplicate-fields/B3 $duplicate-fields/A3 $invalid + end + return + end + return end + local.get $0 + local.get $1 + call $~lib/arraybuffer/ArrayBufferView~visit return end return end - local.get $0 - local.get $1 - call $~lib/arraybuffer/ArrayBufferView~visit return end + local.get $0 + local.get $1 + call $duplicate-fields/A2~visit return end return end local.get $0 local.get $1 - call $duplicate-fields/A2~visit + call $duplicate-fields/B2~visit return end return end local.get $0 local.get $1 - call $duplicate-fields/B2~visit + call $duplicate-fields/B3~visit return end + local.get $0 + local.get $1 + call $duplicate-fields/A3~visit return end unreachable @@ -2567,8 +2631,8 @@ global.get $~lib/memory/__data_end i32.lt_s if - i32.const 16960 - i32.const 17008 + i32.const 16976 + i32.const 17024 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -2888,4 +2952,140 @@ global.set $~lib/memory/__stack_pointer local.get $3 ) + (func $duplicate-fields/A3#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 10 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/A3#set:bar + local.get $0 + local.get $1 + call $duplicate-fields/A3#set:bar + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $duplicate-fields/B3#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.const 9 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + i32.const 0 + call $duplicate-fields/B3#set:bar + global.get $~lib/memory/__stack_pointer + local.get $0 + local.get $1 + call $duplicate-fields/A3#constructor + local.tee $0 + i32.store + local.get $0 + local.get $1 + call $duplicate-fields/B3#set:bar + local.get $0 + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) + (func $export:duplicate-fields/B3#get:bar (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + call $duplicate-fields/B3#get:bar + local.set $1 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $1 + ) + (func $export:duplicate-fields/B3#set:bar (param $0 i32) (param $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + global.get $~lib/memory/__stack_pointer + local.get $1 + i32.store offset=4 + local.get $0 + local.get $1 + call $duplicate-fields/B3#set:bar + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + global.get $~lib/memory/__stack_pointer + local.get $1 + i32.store offset=4 + local.get $0 + local.get $1 + call $duplicate-fields/B3#constructor + local.set $2 + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) ) From b86912ade94feb5aa8b56234ba5a583cf9dc1a50 Mon Sep 17 00:00:00 2001 From: romdotdog <70765447+romdotdog@users.noreply.github.com> Date: Wed, 1 Dec 2021 21:30:11 -0600 Subject: [PATCH 13/13] revise tests + remove overwrite error --- src/diagnosticMessages.generated.ts | 2 - src/diagnosticMessages.json | 1 - src/resolver.ts | 10 +- tests/compiler/duplicate-field-errors.json | 15 +- tests/compiler/duplicate-field-errors.ts | 59 +++-- tests/compiler/duplicate-fields.optimized.wat | 239 ++++++++++++------ tests/compiler/duplicate-fields.ts | 13 +- tests/compiler/duplicate-fields.untouched.wat | 211 ++++++++++------ 8 files changed, 351 insertions(+), 199 deletions(-) diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 1afa167a39..13eaca9da9 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -174,7 +174,6 @@ export enum DiagnosticCode { Expected_0_type_arguments_but_got_1 = 2558, Property_0_has_no_initializer_and_is_not_assigned_in_the_constructor_before_this_is_used_or_returned = 2564, Property_0_is_used_before_being_assigned = 2565, - Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_remove_the_redundant_declaration = 2612, A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums = 2651, Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration = 2673, Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration = 2674, @@ -363,7 +362,6 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2558: return "Expected {0} type arguments, but got {1}."; case 2564: return "Property '{0}' has no initializer and is not assigned in the constructor before 'this' is used or returned."; case 2565: return "Property '{0}' is used before being assigned."; - case 2612: return "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration."; case 2651: return "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums."; case 2673: return "Constructor of class '{0}' is private and only accessible within the class declaration."; case 2674: return "Constructor of class '{0}' is protected and only accessible within the class declaration."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 787dcdf432..7c030a5da6 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -172,7 +172,6 @@ "Expected {0} type arguments, but got {1}.": 2558, "Property '{0}' has no initializer and is not assigned in the constructor before 'this' is used or returned.": 2564, "Property '{0}' is used before being assigned.": 2565, - "Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration.": 2612, "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": 2651, "Constructor of class '{0}' is private and only accessible within the class declaration.": 2673, "Constructor of class '{0}' is protected and only accessible within the class declaration.": 2674, diff --git a/src/resolver.ts b/src/resolver.ts index e5dafb3d03..5903551901 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3196,14 +3196,8 @@ export class Resolver extends DiagnosticEmitter { } } - // assignability checks - if (fieldType.equals(existingField.type) && fieldPrototype.initializerNode === null) { - this.errorRelated( - DiagnosticCode.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_remove_the_redundant_declaration, - fieldPrototype.identifierNode.range, existingField.identifierNode.range, - fieldPrototype.name, baseClass.internalName - ); - } else if (!fieldType.isStrictlyAssignableTo(existingField.type)) { + // assignability + if (!fieldType.isStrictlyAssignableTo(existingField.type)) { this.errorRelated( DiagnosticCode.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, fieldPrototype.identifierNode.range, existingField.identifierNode.range, diff --git a/tests/compiler/duplicate-field-errors.json b/tests/compiler/duplicate-field-errors.json index eff1f143f9..b32e0e0cc0 100644 --- a/tests/compiler/duplicate-field-errors.json +++ b/tests/compiler/duplicate-field-errors.json @@ -2,13 +2,12 @@ "asc_flags": [ ], "stderr": [ - "TS2325: Property 'a' is private in type 'duplicate-field-errors/A' but not in type 'duplicate-field-errors/B'.", - "TS2325: Property 'b' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", - "TS2442: Types have separate declarations of a private property 'c'.", - "TS2416: Property 'd' in type 'duplicate-field-errors/B' is not assignable to the same property in base type 'duplicate-field-errors/A'.", - "TS2612: Property 'e' will overwrite the base property in 'duplicate-field-errors/A'. If this is intentional, add an initializer. Otherwise, remove the redundant declaration.", - "TS2300: Duplicate identifier 'g'.", - "TS2444: Property 'f' is protected in type 'duplicate-field-errors/B' but public in type 'duplicate-field-errors/A'.", - "EOF" + "TS2442: Types have separate declarations of a private property 'privPriv'.", + "TS2325: Property 'privProt' is private in type 'duplicate-field-errors/A' but not in type 'duplicate-field-errors/B'.", + "TS2325: Property 'privPub' is private in type 'duplicate-field-errors/A' but not in type 'duplicate-field-errors/B'.", + "TS2325: Property 'protPriv' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", + "TS2325: Property 'pubPriv' is private in type 'duplicate-field-errors/B' but not in type 'duplicate-field-errors/A'.", + "TS2444: Property 'pubProt' is protected in type 'duplicate-field-errors/B' but public in type 'duplicate-field-errors/A'.", + "TS2300: Duplicate identifier 'method'." ] } diff --git a/tests/compiler/duplicate-field-errors.ts b/tests/compiler/duplicate-field-errors.ts index bd2f1601a1..b68e6f323a 100644 --- a/tests/compiler/duplicate-field-errors.ts +++ b/tests/compiler/duplicate-field-errors.ts @@ -1,33 +1,38 @@ class A { - private a: i32; - public b: i32; - private c: i32; - public d: i64; - public e: i32; - public f: i32; - constructor(a: i32, b: i32, c: i32, d: i64, e: i32, f: i32) { - this.a = a; - this.b = b; - this.c = c; - this.d = d; - this.e = e; - this.f = f; - } - g(): void {} + private privPriv: i32; + private privProt: i32; + private privPub: i32; + + // -- + + protected protPriv: i32; + public pubPriv: i32; + + // -- + + public pubProt: i32; + + // -- + + method(): void {} } export class B extends A { - public a: i32; - private b: i32; - private c: i32; - public d: i32; - public e: i32; - public g: i32; - protected f: i32; - constructor(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { - super(a, b, c, d, e, f); - ERROR("EOF"); - } -} + private privPriv: i32; + protected privProt: i32; + public privPub: i32; + // -- + + private protPriv: i32; + private pubPriv: i32; + + // -- + + protected pubProt: i32; + + // -- + + public method: i32; +} diff --git a/tests/compiler/duplicate-fields.optimized.wat b/tests/compiler/duplicate-fields.optimized.wat index 809ba3ce3b..fbd19917c3 100644 --- a/tests/compiler/duplicate-fields.optimized.wat +++ b/tests/compiler/duplicate-fields.optimized.wat @@ -1,12 +1,12 @@ (module - (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_i32 (func (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (global $~lib/rt/itcms/total (mut i32) (i32.const 0)) (global $~lib/rt/itcms/threshold (mut i32) (i32.const 0)) @@ -38,11 +38,15 @@ (data (i32.const 1504) "\0b\00\00\00 \00\00\00\00\00\00\00 ") (data (i32.const 1532) " \00\00\00\00\00\00\00 \00\00\00\03") (data (i32.const 1556) " ") - (data (i32.const 1568) "\05\00\00\00 \00\00\00\06\00\00\00\00\00\00\00\n") + (data (i32.const 1568) "\05\00\00\00 \00\00\00\06\00\00\00 \00\00\00\n\00\00\00 ") (export "B3" (global $duplicate-fields/B3)) (export "memory" (memory $0)) - (export "B3#get:bar" (func $export:duplicate-fields/B3#get:bar)) - (export "B3#set:bar" (func $export:duplicate-fields/B3#set:bar)) + (export "B3#get:protProt" (func $export:duplicate-fields/B3#get:protProt)) + (export "B3#set:protProt" (func $export:duplicate-fields/B3#set:protProt)) + (export "B3#get:protPub" (func $export:duplicate-fields/B3#get:protPub)) + (export "B3#set:protPub" (func $export:duplicate-fields/B3#set:protPub)) + (export "B3#get:pubPub" (func $export:duplicate-fields/B3#get:pubPub)) + (export "B3#set:pubPub" (func $export:duplicate-fields/B3#set:pubPub)) (export "B3#constructor" (func $export:duplicate-fields/B3#constructor)) (start $~start) (func $~lib/rt/itcms/visitRoots @@ -1776,39 +1780,26 @@ end end ) - (func $duplicate-fields/B2~visit (param $0 i32) - (local $1 i32) - local.get $0 - i32.load - local.tee $1 - if - local.get $1 - call $~lib/rt/itcms/__visit - end - local.get $0 - i32.load - local.tee $0 - if - local.get $0 - call $~lib/rt/itcms/__visit - end - ) (func $~lib/rt/__visit_members (param $0 i32) + (local $1 i32) block $folding-inner0 block $invalid - block $duplicate-fields/B3 - block $duplicate-fields/Bar - block $duplicate-fields/B2 - block $duplicate-fields/Foo - block $duplicate-fields/B - block $duplicate-fields/A - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/A $duplicate-fields/B $folding-inner0 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $duplicate-fields/B3 $folding-inner0 $invalid + block $duplicate-fields/A3 + block $duplicate-fields/B3 + block $duplicate-fields/Bar + block $duplicate-fields/B2 + block $duplicate-fields/Foo + block $duplicate-fields/B + block $duplicate-fields/A + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $folding-inner0 $duplicate-fields/A $duplicate-fields/B $folding-inner0 $duplicate-fields/Foo $duplicate-fields/B2 $duplicate-fields/Bar $duplicate-fields/B3 $duplicate-fields/A3 $invalid + end + return end return end @@ -1818,16 +1809,19 @@ end return end - return + local.get $0 + i32.load + local.tee $1 + if + local.get $1 + call $~lib/rt/itcms/__visit + end + br $folding-inner0 end - local.get $0 - call $duplicate-fields/B2~visit return end return end - local.get $0 - call $duplicate-fields/B2~visit return end unreachable @@ -2135,7 +2129,7 @@ call $~lib/builtins/abort unreachable ) - (func $export:duplicate-fields/B3#get:bar (param $0 i32) (result i32) + (func $export:duplicate-fields/B3#get:protProt (param $0 i32) (result i32) (local $1 i32) global.get $~lib/memory/__stack_pointer i32.const 4 @@ -2163,10 +2157,10 @@ i32.add global.set $~lib/memory/__stack_pointer ) - (func $export:duplicate-fields/B3#set:bar (param $0 i32) (param $1 i32) + (func $export:duplicate-fields/B3#set:protProt (param $0 i32) (param $1 i32) (local $2 i32) global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer @@ -2184,24 +2178,132 @@ local.tee $2 local.get $0 i32.store - local.get $2 + local.get $0 local.get $1 - i32.store offset=4 + i32.store + local.get $2 + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#get:protPub (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + if + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $1 local.get $0 + i32.store + local.get $0 + i32.load offset=4 local.get $1 + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#set:protPub (param $0 i32) (param $1 i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + if + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $2 + local.get $0 i32.store local.get $0 local.get $1 - call $~lib/rt/itcms/__link + i32.store offset=4 + local.get $2 + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#get:pubPub (param $0 i32) (result i32) + (local $1 i32) global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + if + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $1 + local.get $0 + i32.store + local.get $0 + i32.load offset=8 + local.get $1 + i32.const 4 i32.add global.set $~lib/memory/__stack_pointer ) - (func $export:duplicate-fields/B3#constructor (param $0 i32) (param $1 i32) (result i32) + (func $export:duplicate-fields/B3#set:pubPub (param $0 i32) (param $1 i32) (local $2 i32) global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1596 + i32.lt_s + if + i32.const 18000 + i32.const 18048 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $2 + local.get $0 + i32.store + local.get $0 + local.get $1 + i32.store offset=8 + local.get $2 + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#constructor (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer block $folding-inner0 @@ -2210,13 +2312,10 @@ i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer - local.tee $2 + local.tee $1 local.get $0 i32.store - local.get $2 local.get $1 - i32.store offset=4 - local.get $2 i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer @@ -2231,20 +2330,14 @@ i32.eqz if global.get $~lib/memory/__stack_pointer - i32.const 4 + i32.const 12 i32.const 9 call $~lib/rt/itcms/__new local.tee $0 i32.store end - local.get $0 - i32.const 0 - i32.store - local.get $0 - i32.const 0 - call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer - local.tee $2 + local.tee $1 i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer @@ -2259,7 +2352,7 @@ i32.eqz if global.get $~lib/memory/__stack_pointer - i32.const 4 + i32.const 12 i32.const 10 call $~lib/rt/itcms/__new local.tee $0 @@ -2270,32 +2363,32 @@ i32.store local.get $0 i32.const 0 - call $~lib/rt/itcms/__link - local.get $0 - local.get $1 - i32.store + i32.store offset=4 local.get $0 - local.get $1 - call $~lib/rt/itcms/__link + i32.const 0 + i32.store offset=8 global.get $~lib/memory/__stack_pointer i32.const 4 i32.add global.set $~lib/memory/__stack_pointer - local.get $2 + local.get $1 local.get $0 i32.store local.get $0 - local.get $1 + i32.const 0 i32.store local.get $0 - local.get $1 - call $~lib/rt/itcms/__link + i32.const 0 + i32.store offset=4 + local.get $0 + i32.const 0 + i32.store offset=8 global.get $~lib/memory/__stack_pointer i32.const 4 i32.add global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 i32.add global.set $~lib/memory/__stack_pointer local.get $0 diff --git a/tests/compiler/duplicate-fields.ts b/tests/compiler/duplicate-fields.ts index aba5da5e3a..35e6d74f14 100644 --- a/tests/compiler/duplicate-fields.ts +++ b/tests/compiler/duplicate-fields.ts @@ -42,15 +42,16 @@ assert(offsetof("bar") == 0); const raz = new B2(new Bar(1, 2)); assert(raz.bar.bar == 2); -// protected field overriding protected field shouldn't -// throw an error +// make sure visibility checks allow these class A3 { - protected bar: Foo; - constructor(bar: Foo) { this.bar = bar; } + protected protProt: i32; + protected protPub: i32; + public pubPub: i32; } export class B3 extends A3 { - protected bar: Bar; - constructor(bar: Bar) { super(bar); this.bar = bar; } + protected protProt: i32; + public protPub: i32; + public pubPub: i32; } \ No newline at end of file diff --git a/tests/compiler/duplicate-fields.untouched.wat b/tests/compiler/duplicate-fields.untouched.wat index 3be069b8ee..8bf32e91a4 100644 --- a/tests/compiler/duplicate-fields.untouched.wat +++ b/tests/compiler/duplicate-fields.untouched.wat @@ -41,13 +41,17 @@ (data (i32.const 320) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 348) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (data (i32.const 412) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00&\00\00\00d\00u\00p\00l\00i\00c\00a\00t\00e\00-\00f\00i\00e\00l\00d\00s\00.\00t\00s\00\00\00\00\00\00\00") - (data (i32.const 480) "\0b\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\03\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\05\00\00\00 \00\00\00\06\00\00\00\00\00\00\00\n\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 480) "\0b\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\03\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\05\00\00\00 \00\00\00\06\00\00\00 \00\00\00\n\00\00\00 \00\00\00\00\00\00\00") (table $0 1 funcref) (elem $0 (i32.const 1)) (export "B3" (global $duplicate-fields/B3)) (export "memory" (memory $0)) - (export "B3#get:bar" (func $export:duplicate-fields/B3#get:bar)) - (export "B3#set:bar" (func $export:duplicate-fields/B3#set:bar)) + (export "B3#get:protProt" (func $export:duplicate-fields/B3#get:protProt)) + (export "B3#set:protProt" (func $export:duplicate-fields/B3#set:protProt)) + (export "B3#get:protPub" (func $export:duplicate-fields/B3#get:protPub)) + (export "B3#set:protPub" (func $export:duplicate-fields/B3#set:protPub)) + (export "B3#get:pubPub" (func $export:duplicate-fields/B3#get:pubPub)) + (export "B3#set:pubPub" (func $export:duplicate-fields/B3#set:pubPub)) (export "B3#constructor" (func $export:duplicate-fields/B3#constructor)) (start $~start) (func $duplicate-fields/A#set:bar (param $0 i32) (param $1 i32) @@ -2459,28 +2463,48 @@ local.get $1 i32.store offset=4 ) - (func $duplicate-fields/A3#set:bar (param $0 i32) (param $1 i32) + (func $duplicate-fields/A3#set:protProt (param $0 i32) (param $1 i32) local.get $0 local.get $1 i32.store + ) + (func $duplicate-fields/A3#set:protPub (param $0 i32) (param $1 i32) local.get $0 local.get $1 - i32.const 0 - call $~lib/rt/itcms/__link + i32.store offset=4 + ) + (func $duplicate-fields/A3#set:pubPub (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=8 ) - (func $duplicate-fields/B3#set:bar (param $0 i32) (param $1 i32) + (func $duplicate-fields/B3#set:protProt (param $0 i32) (param $1 i32) local.get $0 local.get $1 i32.store + ) + (func $duplicate-fields/B3#set:protPub (param $0 i32) (param $1 i32) local.get $0 local.get $1 - i32.const 0 - call $~lib/rt/itcms/__link + i32.store offset=4 ) - (func $duplicate-fields/B3#get:bar (param $0 i32) (result i32) + (func $duplicate-fields/B3#set:pubPub (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=8 + ) + (func $duplicate-fields/B3#get:protProt (param $0 i32) (result i32) local.get $0 i32.load ) + (func $duplicate-fields/B3#get:protPub (param $0 i32) (result i32) + local.get $0 + i32.load offset=4 + ) + (func $duplicate-fields/B3#get:pubPub (param $0 i32) (result i32) + local.get $0 + i32.load offset=8 + ) (func $~lib/rt/__visit_globals (param $0 i32) (local $1 i32) global.get $duplicate-fields/foo @@ -2540,31 +2564,6 @@ call $~lib/rt/itcms/__visit end ) - (func $duplicate-fields/B3~visit (param $0 i32) (param $1 i32) - (local $2 i32) - local.get $0 - local.get $1 - call $duplicate-fields/A3~visit - local.get $0 - i32.load - local.tee $2 - if - local.get $2 - local.get $1 - call $~lib/rt/itcms/__visit - end - ) - (func $duplicate-fields/A3~visit (param $0 i32) (param $1 i32) - (local $2 i32) - local.get $0 - i32.load - local.tee $2 - if - local.get $2 - local.get $1 - call $~lib/rt/itcms/__visit - end - ) (func $~lib/rt/__visit_members (param $0 i32) (param $1 i32) block $invalid block $duplicate-fields/A3 @@ -2611,14 +2610,8 @@ end return end - local.get $0 - local.get $1 - call $duplicate-fields/B3~visit return end - local.get $0 - local.get $1 - call $duplicate-fields/A3~visit return end unreachable @@ -2952,8 +2945,8 @@ global.set $~lib/memory/__stack_pointer local.get $3 ) - (func $duplicate-fields/A3#constructor (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) + (func $duplicate-fields/A3#constructor (param $0 i32) (result i32) + (local $1 i32) global.get $~lib/memory/__stack_pointer i32.const 4 i32.sub @@ -2966,7 +2959,7 @@ i32.eqz if global.get $~lib/memory/__stack_pointer - i32.const 4 + i32.const 12 i32.const 10 call $~lib/rt/itcms/__new local.tee $0 @@ -2974,20 +2967,23 @@ end local.get $0 i32.const 0 - call $duplicate-fields/A3#set:bar + call $duplicate-fields/A3#set:protProt local.get $0 - local.get $1 - call $duplicate-fields/A3#set:bar + i32.const 0 + call $duplicate-fields/A3#set:protPub local.get $0 - local.set $2 + i32.const 0 + call $duplicate-fields/A3#set:pubPub + local.get $0 + local.set $1 global.get $~lib/memory/__stack_pointer i32.const 4 i32.add global.set $~lib/memory/__stack_pointer - local.get $2 + local.get $1 ) - (func $duplicate-fields/B3#constructor (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) + (func $duplicate-fields/B3#constructor (param $0 i32) (result i32) + (local $1 i32) global.get $~lib/memory/__stack_pointer i32.const 4 i32.sub @@ -3000,33 +2996,35 @@ i32.eqz if global.get $~lib/memory/__stack_pointer - i32.const 4 + i32.const 12 i32.const 9 call $~lib/rt/itcms/__new local.tee $0 i32.store end - local.get $0 - i32.const 0 - call $duplicate-fields/B3#set:bar global.get $~lib/memory/__stack_pointer local.get $0 - local.get $1 call $duplicate-fields/A3#constructor local.tee $0 i32.store local.get $0 - local.get $1 - call $duplicate-fields/B3#set:bar + i32.const 0 + call $duplicate-fields/B3#set:protProt local.get $0 - local.set $2 + i32.const 0 + call $duplicate-fields/B3#set:protPub + local.get $0 + i32.const 0 + call $duplicate-fields/B3#set:pubPub + local.get $0 + local.set $1 global.get $~lib/memory/__stack_pointer i32.const 4 i32.add global.set $~lib/memory/__stack_pointer - local.get $2 + local.get $1 ) - (func $export:duplicate-fields/B3#get:bar (param $0 i32) (result i32) + (func $export:duplicate-fields/B3#get:protProt (param $0 i32) (result i32) (local $1 i32) global.get $~lib/memory/__stack_pointer i32.const 4 @@ -3037,7 +3035,7 @@ local.get $0 i32.store local.get $0 - call $duplicate-fields/B3#get:bar + call $duplicate-fields/B3#get:protProt local.set $1 global.get $~lib/memory/__stack_pointer i32.const 4 @@ -3045,47 +3043,112 @@ global.set $~lib/memory/__stack_pointer local.get $1 ) - (func $export:duplicate-fields/B3#set:bar (param $0 i32) (param $1 i32) + (func $export:duplicate-fields/B3#set:protProt (param $0 i32) (param $1 i32) global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + local.get $1 + call $duplicate-fields/B3#set:protProt + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#get:protPub (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer call $~stack_check global.get $~lib/memory/__stack_pointer local.get $0 i32.store + local.get $0 + call $duplicate-fields/B3#get:protPub + local.set $1 global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer local.get $1 - i32.store offset=4 + ) + (func $export:duplicate-fields/B3#set:protPub (param $0 i32) (param $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store local.get $0 local.get $1 - call $duplicate-fields/B3#set:bar + call $duplicate-fields/B3#set:protPub global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 i32.add global.set $~lib/memory/__stack_pointer ) - (func $export:duplicate-fields/B3#constructor (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) + (func $export:duplicate-fields/B3#get:pubPub (param $0 i32) (result i32) + (local $1 i32) global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 i32.sub global.set $~lib/memory/__stack_pointer call $~stack_check global.get $~lib/memory/__stack_pointer local.get $0 i32.store + local.get $0 + call $duplicate-fields/B3#get:pubPub + local.set $1 global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer local.get $1 - i32.store offset=4 + ) + (func $export:duplicate-fields/B3#set:pubPub (param $0 i32) (param $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store local.get $0 local.get $1 + call $duplicate-fields/B3#set:pubPub + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $export:duplicate-fields/B3#constructor (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 call $duplicate-fields/B3#constructor - local.set $2 + local.set $1 global.get $~lib/memory/__stack_pointer - i32.const 8 + i32.const 4 i32.add global.set $~lib/memory/__stack_pointer - local.get $2 + local.get $1 ) )