jslike 1.8.2 → 1.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -12250,6 +12250,10 @@ function getPatternName(pattern) {
12250
12250
  return pattern.name;
12251
12251
  }
12252
12252
 
12253
+ function unwrapTSParameterProperty(param) {
12254
+ return param?.type === 'TSParameterProperty' ? param.parameter : param;
12255
+ }
12256
+
12253
12257
  function collectRuntimeIdentifierReferences(node) {
12254
12258
  const references = new Set();
12255
12259
  const skipKeys = new Set([
@@ -13871,34 +13875,7 @@ class Interpreter {
13871
13875
  funcEnv.define('this', thisContext);
13872
13876
  }
13873
13877
 
13874
- // Bind parameters
13875
- for (let i = 0; i < metadata.params.length; i++) {
13876
- const param = metadata.params[i].type === 'TSParameterProperty'
13877
- ? metadata.params[i].parameter
13878
- : metadata.params[i];
13879
-
13880
- if (param.type === 'Identifier') {
13881
- // Simple parameter: function(x)
13882
- funcEnv.define(param.name, args[i]);
13883
- } else if (param.type === 'AssignmentPattern') {
13884
- // Default parameter: function(x = defaultValue)
13885
- const value = args[i] !== undefined ? args[i] : this.evaluate(param.right, funcEnv);
13886
- funcEnv.define(param.left.name, value);
13887
- } else if (param.type === 'RestElement') {
13888
- // Rest parameter: function(...rest)
13889
- funcEnv.define(param.argument.name, args.slice(i));
13890
- break; // Rest element must be last
13891
- } else if (param.type === 'ObjectPattern') {
13892
- // Destructuring parameter: function({a, b})
13893
- this.bindObjectPattern(param, args[i], funcEnv);
13894
- } else if (param.type === 'ArrayPattern') {
13895
- // Array destructuring parameter: function([a, b])
13896
- this.bindArrayPattern(param, args[i], funcEnv);
13897
- } else {
13898
- // Fallback for simple parameter names
13899
- funcEnv.define(param.name, args[i]);
13900
- }
13901
- }
13878
+ this.bindFunctionParameters(metadata.params, args, funcEnv);
13902
13879
 
13903
13880
  // Execute function body
13904
13881
  // If async, use async evaluation and return a promise
@@ -14255,7 +14232,7 @@ class Interpreter {
14255
14232
  const finalValue = propValue !== undefined
14256
14233
  ? propValue
14257
14234
  : this.evaluate(prop.value.right, env);
14258
- env.define(prop.value.left.name, finalValue, isConst);
14235
+ this.bindPattern(prop.value.left, finalValue, env, isConst);
14259
14236
  } else if (prop.value.type === 'ObjectPattern') {
14260
14237
  this.bindObjectPattern(prop.value, propValue, env, isConst);
14261
14238
  } else if (prop.value.type === 'ArrayPattern') {
@@ -14286,7 +14263,7 @@ class Interpreter {
14286
14263
  const finalValue = value[i] !== undefined
14287
14264
  ? value[i]
14288
14265
  : this.evaluate(element.right, env);
14289
- env.define(element.left.name, finalValue, isConst);
14266
+ this.bindPattern(element.left, finalValue, env, isConst);
14290
14267
  } else if (element.type === 'ObjectPattern') {
14291
14268
  this.bindObjectPattern(element, value[i], env, isConst);
14292
14269
  } else if (element.type === 'ArrayPattern') {
@@ -14295,6 +14272,78 @@ class Interpreter {
14295
14272
  }
14296
14273
  }
14297
14274
 
14275
+ bindPattern(pattern, value, env, isConst = false) {
14276
+ if (pattern.type === 'Identifier') {
14277
+ env.define(pattern.name, value, isConst);
14278
+ } else if (pattern.type === 'ObjectPattern') {
14279
+ this.bindObjectPattern(pattern, value, env, isConst);
14280
+ } else if (pattern.type === 'ArrayPattern') {
14281
+ this.bindArrayPattern(pattern, value, env, isConst);
14282
+ } else if (pattern.type === 'AssignmentPattern') {
14283
+ const finalValue = value !== undefined ? value : this.evaluate(pattern.right, env);
14284
+ this.bindPattern(pattern.left, finalValue, env, isConst);
14285
+ } else if (pattern.type === 'RestElement') {
14286
+ this.bindPattern(pattern.argument, value, env, isConst);
14287
+ }
14288
+ }
14289
+
14290
+ bindFunctionParameters(params, args, env, thisContext = null) {
14291
+ for (let i = 0; i < params.length; i++) {
14292
+ const originalParam = params[i];
14293
+ const param = unwrapTSParameterProperty(originalParam);
14294
+
14295
+ this.bindFunctionParameter(param, args[i], args.slice(i), env);
14296
+
14297
+ if (originalParam.type === 'TSParameterProperty' && thisContext) {
14298
+ const propertyName = getPatternName(originalParam.parameter);
14299
+ if (propertyName) {
14300
+ thisContext[propertyName] = env.get(propertyName);
14301
+ }
14302
+ }
14303
+
14304
+ if (param.type === 'RestElement') {
14305
+ break;
14306
+ }
14307
+ }
14308
+ }
14309
+
14310
+ bindFunctionParameter(param, arg, restArgs, env) {
14311
+ if (param.type === 'Identifier') {
14312
+ this.bindPattern(param, arg, env);
14313
+ return;
14314
+ }
14315
+
14316
+ if (param.type === 'AssignmentPattern') {
14317
+ const value = arg !== undefined ? arg : this.evaluate(param.right, env);
14318
+ this.bindPattern(param.left, value, env);
14319
+ return;
14320
+ }
14321
+
14322
+ if (param.type === 'RestElement') {
14323
+ const target = param.argument;
14324
+ if (target.type === 'Identifier') {
14325
+ env.define(target.name, restArgs);
14326
+ } else if (target.type === 'ArrayPattern') {
14327
+ this.bindArrayPattern(target, restArgs, env);
14328
+ } else if (target.type === 'ObjectPattern') {
14329
+ this.bindObjectPattern(target, restArgs, env);
14330
+ }
14331
+ return;
14332
+ }
14333
+
14334
+ if (param.type === 'ObjectPattern') {
14335
+ this.bindPattern(param, arg, env);
14336
+ return;
14337
+ }
14338
+
14339
+ if (param.type === 'ArrayPattern') {
14340
+ this.bindPattern(param, arg, env);
14341
+ return;
14342
+ }
14343
+
14344
+ env.define(param.name, arg);
14345
+ }
14346
+
14298
14347
  evaluateFunctionDeclaration(node, env) {
14299
14348
  const funcMetadata = {
14300
14349
  __isFunction: true,
@@ -14859,6 +14908,7 @@ class Interpreter {
14859
14908
  let constructor = null;
14860
14909
  const methods = {};
14861
14910
  const staticMethods = {};
14911
+ const instanceFields = [];
14862
14912
 
14863
14913
  for (const member of node.body.body) {
14864
14914
  if (member.type === 'MethodDefinition') {
@@ -14872,6 +14922,8 @@ class Interpreter {
14872
14922
  } else {
14873
14923
  methods[methodName] = methodFunc;
14874
14924
  }
14925
+ } else if (member.type === 'PropertyDefinition' && !member.static && !member.declare && !member.abstract) {
14926
+ instanceFields.push(member);
14875
14927
  }
14876
14928
  }
14877
14929
 
@@ -14879,18 +14931,11 @@ class Interpreter {
14879
14931
  const classConstructor = function(...args) {
14880
14932
  // Create instance
14881
14933
  const instance = Object.create(classConstructor.prototype);
14934
+ const result = interpreter.constructClassInto(classConstructor, instance, args, env);
14882
14935
 
14883
- // Call constructor - super() must be called explicitly inside constructor
14884
- if (constructor) {
14885
- const result = interpreter.callMethodFunction(constructor, instance, args, env, superClass);
14886
- // Only use the returned object if it's an explicit return of an object (not the instance)
14887
- if (result && result.__explicitReturn && result.value && typeof result.value === 'object' && result.value !== instance) {
14888
- return result.value;
14889
- }
14890
- } else if (superClass) {
14891
- // If no constructor defined but has superClass, implicitly call super()
14892
- // Call the superClass constructor properly - it's a classConstructor function
14893
- superClass.call(instance, ...args);
14936
+ // Only use the returned object if it's an explicit return of an object (not the instance)
14937
+ if (result && result.__explicitReturn && result.value && typeof result.value === 'object' && result.value !== instance) {
14938
+ return result.value;
14894
14939
  }
14895
14940
 
14896
14941
  return instance;
@@ -14901,6 +14946,12 @@ class Interpreter {
14901
14946
  classConstructor.__constructor = constructor;
14902
14947
  }
14903
14948
 
14949
+ classConstructor.__instanceFields = instanceFields;
14950
+ classConstructor.__superClass = superClass;
14951
+ classConstructor.__constructInto = (instance, args) => {
14952
+ return interpreter.constructClassInto(classConstructor, instance, args, env);
14953
+ };
14954
+
14904
14955
  // Set up prototype chain
14905
14956
  if (superClass) {
14906
14957
  classConstructor.prototype = Object.create(superClass.prototype);
@@ -14935,6 +14986,69 @@ class Interpreter {
14935
14986
  return classConstructor;
14936
14987
  }
14937
14988
 
14989
+ constructClassInto(classConstructor, instance, args, env) {
14990
+ const superClass = classConstructor.__superClass;
14991
+ const constructor = classConstructor.__constructor;
14992
+ let fieldsInitialized = false;
14993
+
14994
+ const initializeOwnFields = () => {
14995
+ if (!fieldsInitialized) {
14996
+ this.initializeClassFields(classConstructor, instance, env);
14997
+ fieldsInitialized = true;
14998
+ }
14999
+ };
15000
+
15001
+ if (!superClass) {
15002
+ initializeOwnFields();
15003
+ if (constructor) {
15004
+ return this.callMethodFunction(constructor, instance, args, env, null);
15005
+ }
15006
+ return undefined;
15007
+ }
15008
+
15009
+ if (constructor) {
15010
+ const result = this.callMethodFunction(constructor, instance, args, env, superClass, initializeOwnFields);
15011
+ initializeOwnFields();
15012
+ return result;
15013
+ }
15014
+
15015
+ this.initializeSuperClass(superClass, instance, args);
15016
+ initializeOwnFields();
15017
+ return undefined;
15018
+ }
15019
+
15020
+ initializeSuperClass(superClass, instance, args) {
15021
+ if (superClass.__constructInto) {
15022
+ return superClass.__constructInto(instance, args);
15023
+ }
15024
+
15025
+ // For native constructors like Error, use Reflect.construct and copy instance properties.
15026
+ const tempInstance = Reflect.construct(superClass, args, instance.constructor);
15027
+ Object.getOwnPropertyNames(tempInstance).forEach(name => {
15028
+ instance[name] = tempInstance[name];
15029
+ });
15030
+ return undefined;
15031
+ }
15032
+
15033
+ initializeClassFields(classConstructor, instance, env) {
15034
+ for (const field of classConstructor.__instanceFields || []) {
15035
+ const fieldEnv = new Environment(env);
15036
+ fieldEnv.define('this', instance);
15037
+ const name = this.getClassFieldName(field, fieldEnv);
15038
+ instance[name] = field.value ? this.evaluate(field.value, fieldEnv) : undefined;
15039
+ }
15040
+ }
15041
+
15042
+ getClassFieldName(field, env) {
15043
+ if (field.computed) {
15044
+ return this.evaluate(field.key, env);
15045
+ }
15046
+ if (field.key.type === 'Identifier' || field.key.type === 'PrivateIdentifier') {
15047
+ return field.key.name;
15048
+ }
15049
+ return field.key.value;
15050
+ }
15051
+
14938
15052
  createMethodFunction(funcNode, env, className) {
14939
15053
  const func = {
14940
15054
  __isFunction: true,
@@ -14946,7 +15060,7 @@ class Interpreter {
14946
15060
  return func;
14947
15061
  }
14948
15062
 
14949
- callMethodFunction(methodFunc, thisContext, args, env, superClass = null) {
15063
+ callMethodFunction(methodFunc, thisContext, args, env, superClass = null, afterSuper = null) {
14950
15064
  const funcEnv = new Environment(methodFunc.__env || env);
14951
15065
 
14952
15066
  // Bind 'this'
@@ -14956,21 +15070,11 @@ class Interpreter {
14956
15070
  if (superClass) {
14957
15071
  // Create a super function that calls the parent constructor
14958
15072
  const superFunc = (...superArgs) => {
14959
- // Call the parent constructor method if it exists
14960
- if (superClass.__constructor) {
14961
- this.callMethodFunction(superClass.__constructor, thisContext, superArgs, env, null);
14962
- }
14963
- // Otherwise, call superClass as a regular constructor (for native/external classes)
14964
- else {
14965
- // For native constructors like Error, we need to use Reflect.construct
14966
- // to properly initialize the instance properties
14967
- const tempInstance = Reflect.construct(superClass, superArgs, thisContext.constructor);
14968
- // Copy properties from the temp instance to our thisContext
14969
- Object.getOwnPropertyNames(tempInstance).forEach(name => {
14970
- thisContext[name] = tempInstance[name];
14971
- });
15073
+ const result = this.initializeSuperClass(superClass, thisContext, superArgs);
15074
+ if (afterSuper) {
15075
+ afterSuper();
14972
15076
  }
14973
- return undefined;
15077
+ return result && result.__explicitReturn ? result.value : undefined;
14974
15078
  };
14975
15079
  // Store both the function and mark it as super
14976
15080
  superFunc.__isSuperConstructor = true;
@@ -14978,42 +15082,7 @@ class Interpreter {
14978
15082
  funcEnv.define('super', superFunc);
14979
15083
  }
14980
15084
 
14981
- // Bind parameters
14982
- for (let i = 0; i < methodFunc.__params.length; i++) {
14983
- const originalParam = methodFunc.__params[i];
14984
- const param = originalParam.type === 'TSParameterProperty'
14985
- ? originalParam.parameter
14986
- : originalParam;
14987
-
14988
- if (param.type === 'Identifier') {
14989
- // Simple parameter: function(x)
14990
- funcEnv.define(param.name, args[i]);
14991
- } else if (param.type === 'AssignmentPattern') {
14992
- // Default parameter: function(x = defaultValue)
14993
- const value = args[i] !== undefined ? args[i] : this.evaluate(param.right, funcEnv);
14994
- funcEnv.define(param.left.name, value);
14995
- } else if (param.type === 'RestElement') {
14996
- // Rest parameter: function(...rest)
14997
- funcEnv.define(param.argument.name, args.slice(i));
14998
- break; // Rest element must be last
14999
- } else if (param.type === 'ObjectPattern') {
15000
- // Destructuring parameter: function({a, b})
15001
- this.bindObjectPattern(param, args[i], funcEnv);
15002
- } else if (param.type === 'ArrayPattern') {
15003
- // Array destructuring parameter: function([a, b])
15004
- this.bindArrayPattern(param, args[i], funcEnv);
15005
- } else {
15006
- // Fallback for simple parameter names
15007
- funcEnv.define(param.name, args[i]);
15008
- }
15009
-
15010
- if (originalParam.type === 'TSParameterProperty') {
15011
- const propertyName = getPatternName(originalParam.parameter);
15012
- if (propertyName) {
15013
- thisContext[propertyName] = funcEnv.get(propertyName);
15014
- }
15015
- }
15016
- }
15085
+ this.bindFunctionParameters(methodFunc.__params, args, funcEnv, thisContext);
15017
15086
 
15018
15087
  const result = this.evaluate(methodFunc.__body, funcEnv);
15019
15088
 
package/dist/index.d.ts CHANGED
@@ -12250,6 +12250,10 @@ function getPatternName(pattern) {
12250
12250
  return pattern.name;
12251
12251
  }
12252
12252
 
12253
+ function unwrapTSParameterProperty(param) {
12254
+ return param?.type === 'TSParameterProperty' ? param.parameter : param;
12255
+ }
12256
+
12253
12257
  function collectRuntimeIdentifierReferences(node) {
12254
12258
  const references = new Set();
12255
12259
  const skipKeys = new Set([
@@ -13871,34 +13875,7 @@ class Interpreter {
13871
13875
  funcEnv.define('this', thisContext);
13872
13876
  }
13873
13877
 
13874
- // Bind parameters
13875
- for (let i = 0; i < metadata.params.length; i++) {
13876
- const param = metadata.params[i].type === 'TSParameterProperty'
13877
- ? metadata.params[i].parameter
13878
- : metadata.params[i];
13879
-
13880
- if (param.type === 'Identifier') {
13881
- // Simple parameter: function(x)
13882
- funcEnv.define(param.name, args[i]);
13883
- } else if (param.type === 'AssignmentPattern') {
13884
- // Default parameter: function(x = defaultValue)
13885
- const value = args[i] !== undefined ? args[i] : this.evaluate(param.right, funcEnv);
13886
- funcEnv.define(param.left.name, value);
13887
- } else if (param.type === 'RestElement') {
13888
- // Rest parameter: function(...rest)
13889
- funcEnv.define(param.argument.name, args.slice(i));
13890
- break; // Rest element must be last
13891
- } else if (param.type === 'ObjectPattern') {
13892
- // Destructuring parameter: function({a, b})
13893
- this.bindObjectPattern(param, args[i], funcEnv);
13894
- } else if (param.type === 'ArrayPattern') {
13895
- // Array destructuring parameter: function([a, b])
13896
- this.bindArrayPattern(param, args[i], funcEnv);
13897
- } else {
13898
- // Fallback for simple parameter names
13899
- funcEnv.define(param.name, args[i]);
13900
- }
13901
- }
13878
+ this.bindFunctionParameters(metadata.params, args, funcEnv);
13902
13879
 
13903
13880
  // Execute function body
13904
13881
  // If async, use async evaluation and return a promise
@@ -14255,7 +14232,7 @@ class Interpreter {
14255
14232
  const finalValue = propValue !== undefined
14256
14233
  ? propValue
14257
14234
  : this.evaluate(prop.value.right, env);
14258
- env.define(prop.value.left.name, finalValue, isConst);
14235
+ this.bindPattern(prop.value.left, finalValue, env, isConst);
14259
14236
  } else if (prop.value.type === 'ObjectPattern') {
14260
14237
  this.bindObjectPattern(prop.value, propValue, env, isConst);
14261
14238
  } else if (prop.value.type === 'ArrayPattern') {
@@ -14286,7 +14263,7 @@ class Interpreter {
14286
14263
  const finalValue = value[i] !== undefined
14287
14264
  ? value[i]
14288
14265
  : this.evaluate(element.right, env);
14289
- env.define(element.left.name, finalValue, isConst);
14266
+ this.bindPattern(element.left, finalValue, env, isConst);
14290
14267
  } else if (element.type === 'ObjectPattern') {
14291
14268
  this.bindObjectPattern(element, value[i], env, isConst);
14292
14269
  } else if (element.type === 'ArrayPattern') {
@@ -14295,6 +14272,78 @@ class Interpreter {
14295
14272
  }
14296
14273
  }
14297
14274
 
14275
+ bindPattern(pattern, value, env, isConst = false) {
14276
+ if (pattern.type === 'Identifier') {
14277
+ env.define(pattern.name, value, isConst);
14278
+ } else if (pattern.type === 'ObjectPattern') {
14279
+ this.bindObjectPattern(pattern, value, env, isConst);
14280
+ } else if (pattern.type === 'ArrayPattern') {
14281
+ this.bindArrayPattern(pattern, value, env, isConst);
14282
+ } else if (pattern.type === 'AssignmentPattern') {
14283
+ const finalValue = value !== undefined ? value : this.evaluate(pattern.right, env);
14284
+ this.bindPattern(pattern.left, finalValue, env, isConst);
14285
+ } else if (pattern.type === 'RestElement') {
14286
+ this.bindPattern(pattern.argument, value, env, isConst);
14287
+ }
14288
+ }
14289
+
14290
+ bindFunctionParameters(params, args, env, thisContext = null) {
14291
+ for (let i = 0; i < params.length; i++) {
14292
+ const originalParam = params[i];
14293
+ const param = unwrapTSParameterProperty(originalParam);
14294
+
14295
+ this.bindFunctionParameter(param, args[i], args.slice(i), env);
14296
+
14297
+ if (originalParam.type === 'TSParameterProperty' && thisContext) {
14298
+ const propertyName = getPatternName(originalParam.parameter);
14299
+ if (propertyName) {
14300
+ thisContext[propertyName] = env.get(propertyName);
14301
+ }
14302
+ }
14303
+
14304
+ if (param.type === 'RestElement') {
14305
+ break;
14306
+ }
14307
+ }
14308
+ }
14309
+
14310
+ bindFunctionParameter(param, arg, restArgs, env) {
14311
+ if (param.type === 'Identifier') {
14312
+ this.bindPattern(param, arg, env);
14313
+ return;
14314
+ }
14315
+
14316
+ if (param.type === 'AssignmentPattern') {
14317
+ const value = arg !== undefined ? arg : this.evaluate(param.right, env);
14318
+ this.bindPattern(param.left, value, env);
14319
+ return;
14320
+ }
14321
+
14322
+ if (param.type === 'RestElement') {
14323
+ const target = param.argument;
14324
+ if (target.type === 'Identifier') {
14325
+ env.define(target.name, restArgs);
14326
+ } else if (target.type === 'ArrayPattern') {
14327
+ this.bindArrayPattern(target, restArgs, env);
14328
+ } else if (target.type === 'ObjectPattern') {
14329
+ this.bindObjectPattern(target, restArgs, env);
14330
+ }
14331
+ return;
14332
+ }
14333
+
14334
+ if (param.type === 'ObjectPattern') {
14335
+ this.bindPattern(param, arg, env);
14336
+ return;
14337
+ }
14338
+
14339
+ if (param.type === 'ArrayPattern') {
14340
+ this.bindPattern(param, arg, env);
14341
+ return;
14342
+ }
14343
+
14344
+ env.define(param.name, arg);
14345
+ }
14346
+
14298
14347
  evaluateFunctionDeclaration(node, env) {
14299
14348
  const funcMetadata = {
14300
14349
  __isFunction: true,
@@ -14859,6 +14908,7 @@ class Interpreter {
14859
14908
  let constructor = null;
14860
14909
  const methods = {};
14861
14910
  const staticMethods = {};
14911
+ const instanceFields = [];
14862
14912
 
14863
14913
  for (const member of node.body.body) {
14864
14914
  if (member.type === 'MethodDefinition') {
@@ -14872,6 +14922,8 @@ class Interpreter {
14872
14922
  } else {
14873
14923
  methods[methodName] = methodFunc;
14874
14924
  }
14925
+ } else if (member.type === 'PropertyDefinition' && !member.static && !member.declare && !member.abstract) {
14926
+ instanceFields.push(member);
14875
14927
  }
14876
14928
  }
14877
14929
 
@@ -14879,18 +14931,11 @@ class Interpreter {
14879
14931
  const classConstructor = function(...args) {
14880
14932
  // Create instance
14881
14933
  const instance = Object.create(classConstructor.prototype);
14934
+ const result = interpreter.constructClassInto(classConstructor, instance, args, env);
14882
14935
 
14883
- // Call constructor - super() must be called explicitly inside constructor
14884
- if (constructor) {
14885
- const result = interpreter.callMethodFunction(constructor, instance, args, env, superClass);
14886
- // Only use the returned object if it's an explicit return of an object (not the instance)
14887
- if (result && result.__explicitReturn && result.value && typeof result.value === 'object' && result.value !== instance) {
14888
- return result.value;
14889
- }
14890
- } else if (superClass) {
14891
- // If no constructor defined but has superClass, implicitly call super()
14892
- // Call the superClass constructor properly - it's a classConstructor function
14893
- superClass.call(instance, ...args);
14936
+ // Only use the returned object if it's an explicit return of an object (not the instance)
14937
+ if (result && result.__explicitReturn && result.value && typeof result.value === 'object' && result.value !== instance) {
14938
+ return result.value;
14894
14939
  }
14895
14940
 
14896
14941
  return instance;
@@ -14901,6 +14946,12 @@ class Interpreter {
14901
14946
  classConstructor.__constructor = constructor;
14902
14947
  }
14903
14948
 
14949
+ classConstructor.__instanceFields = instanceFields;
14950
+ classConstructor.__superClass = superClass;
14951
+ classConstructor.__constructInto = (instance, args) => {
14952
+ return interpreter.constructClassInto(classConstructor, instance, args, env);
14953
+ };
14954
+
14904
14955
  // Set up prototype chain
14905
14956
  if (superClass) {
14906
14957
  classConstructor.prototype = Object.create(superClass.prototype);
@@ -14935,6 +14986,69 @@ class Interpreter {
14935
14986
  return classConstructor;
14936
14987
  }
14937
14988
 
14989
+ constructClassInto(classConstructor, instance, args, env) {
14990
+ const superClass = classConstructor.__superClass;
14991
+ const constructor = classConstructor.__constructor;
14992
+ let fieldsInitialized = false;
14993
+
14994
+ const initializeOwnFields = () => {
14995
+ if (!fieldsInitialized) {
14996
+ this.initializeClassFields(classConstructor, instance, env);
14997
+ fieldsInitialized = true;
14998
+ }
14999
+ };
15000
+
15001
+ if (!superClass) {
15002
+ initializeOwnFields();
15003
+ if (constructor) {
15004
+ return this.callMethodFunction(constructor, instance, args, env, null);
15005
+ }
15006
+ return undefined;
15007
+ }
15008
+
15009
+ if (constructor) {
15010
+ const result = this.callMethodFunction(constructor, instance, args, env, superClass, initializeOwnFields);
15011
+ initializeOwnFields();
15012
+ return result;
15013
+ }
15014
+
15015
+ this.initializeSuperClass(superClass, instance, args);
15016
+ initializeOwnFields();
15017
+ return undefined;
15018
+ }
15019
+
15020
+ initializeSuperClass(superClass, instance, args) {
15021
+ if (superClass.__constructInto) {
15022
+ return superClass.__constructInto(instance, args);
15023
+ }
15024
+
15025
+ // For native constructors like Error, use Reflect.construct and copy instance properties.
15026
+ const tempInstance = Reflect.construct(superClass, args, instance.constructor);
15027
+ Object.getOwnPropertyNames(tempInstance).forEach(name => {
15028
+ instance[name] = tempInstance[name];
15029
+ });
15030
+ return undefined;
15031
+ }
15032
+
15033
+ initializeClassFields(classConstructor, instance, env) {
15034
+ for (const field of classConstructor.__instanceFields || []) {
15035
+ const fieldEnv = new Environment(env);
15036
+ fieldEnv.define('this', instance);
15037
+ const name = this.getClassFieldName(field, fieldEnv);
15038
+ instance[name] = field.value ? this.evaluate(field.value, fieldEnv) : undefined;
15039
+ }
15040
+ }
15041
+
15042
+ getClassFieldName(field, env) {
15043
+ if (field.computed) {
15044
+ return this.evaluate(field.key, env);
15045
+ }
15046
+ if (field.key.type === 'Identifier' || field.key.type === 'PrivateIdentifier') {
15047
+ return field.key.name;
15048
+ }
15049
+ return field.key.value;
15050
+ }
15051
+
14938
15052
  createMethodFunction(funcNode, env, className) {
14939
15053
  const func = {
14940
15054
  __isFunction: true,
@@ -14946,7 +15060,7 @@ class Interpreter {
14946
15060
  return func;
14947
15061
  }
14948
15062
 
14949
- callMethodFunction(methodFunc, thisContext, args, env, superClass = null) {
15063
+ callMethodFunction(methodFunc, thisContext, args, env, superClass = null, afterSuper = null) {
14950
15064
  const funcEnv = new Environment(methodFunc.__env || env);
14951
15065
 
14952
15066
  // Bind 'this'
@@ -14956,21 +15070,11 @@ class Interpreter {
14956
15070
  if (superClass) {
14957
15071
  // Create a super function that calls the parent constructor
14958
15072
  const superFunc = (...superArgs) => {
14959
- // Call the parent constructor method if it exists
14960
- if (superClass.__constructor) {
14961
- this.callMethodFunction(superClass.__constructor, thisContext, superArgs, env, null);
14962
- }
14963
- // Otherwise, call superClass as a regular constructor (for native/external classes)
14964
- else {
14965
- // For native constructors like Error, we need to use Reflect.construct
14966
- // to properly initialize the instance properties
14967
- const tempInstance = Reflect.construct(superClass, superArgs, thisContext.constructor);
14968
- // Copy properties from the temp instance to our thisContext
14969
- Object.getOwnPropertyNames(tempInstance).forEach(name => {
14970
- thisContext[name] = tempInstance[name];
14971
- });
15073
+ const result = this.initializeSuperClass(superClass, thisContext, superArgs);
15074
+ if (afterSuper) {
15075
+ afterSuper();
14972
15076
  }
14973
- return undefined;
15077
+ return result && result.__explicitReturn ? result.value : undefined;
14974
15078
  };
14975
15079
  // Store both the function and mark it as super
14976
15080
  superFunc.__isSuperConstructor = true;
@@ -14978,42 +15082,7 @@ class Interpreter {
14978
15082
  funcEnv.define('super', superFunc);
14979
15083
  }
14980
15084
 
14981
- // Bind parameters
14982
- for (let i = 0; i < methodFunc.__params.length; i++) {
14983
- const originalParam = methodFunc.__params[i];
14984
- const param = originalParam.type === 'TSParameterProperty'
14985
- ? originalParam.parameter
14986
- : originalParam;
14987
-
14988
- if (param.type === 'Identifier') {
14989
- // Simple parameter: function(x)
14990
- funcEnv.define(param.name, args[i]);
14991
- } else if (param.type === 'AssignmentPattern') {
14992
- // Default parameter: function(x = defaultValue)
14993
- const value = args[i] !== undefined ? args[i] : this.evaluate(param.right, funcEnv);
14994
- funcEnv.define(param.left.name, value);
14995
- } else if (param.type === 'RestElement') {
14996
- // Rest parameter: function(...rest)
14997
- funcEnv.define(param.argument.name, args.slice(i));
14998
- break; // Rest element must be last
14999
- } else if (param.type === 'ObjectPattern') {
15000
- // Destructuring parameter: function({a, b})
15001
- this.bindObjectPattern(param, args[i], funcEnv);
15002
- } else if (param.type === 'ArrayPattern') {
15003
- // Array destructuring parameter: function([a, b])
15004
- this.bindArrayPattern(param, args[i], funcEnv);
15005
- } else {
15006
- // Fallback for simple parameter names
15007
- funcEnv.define(param.name, args[i]);
15008
- }
15009
-
15010
- if (originalParam.type === 'TSParameterProperty') {
15011
- const propertyName = getPatternName(originalParam.parameter);
15012
- if (propertyName) {
15013
- thisContext[propertyName] = funcEnv.get(propertyName);
15014
- }
15015
- }
15016
- }
15085
+ this.bindFunctionParameters(methodFunc.__params, args, funcEnv, thisContext);
15017
15086
 
15018
15087
  const result = this.evaluate(methodFunc.__body, funcEnv);
15019
15088