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/esm/interpreter/interpreter.js +161 -92
- package/dist/index.cjs +137 -61
- package/dist/index.d.cts +161 -92
- package/dist/index.d.ts +161 -92
- package/dist/index.js +137 -61
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
14884
|
-
if (
|
|
14885
|
-
|
|
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
|
-
|
|
14960
|
-
if (
|
|
14961
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
14884
|
-
if (
|
|
14885
|
-
|
|
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
|
-
|
|
14960
|
-
if (
|
|
14961
|
-
|
|
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
|
-
|
|
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
|
|