jitar
Version:
Distributed runtime for JavaScript and TypeScript to chop monolithic applications into micros.
1 lines • 81.5 kB
JavaScript
class BadRequest extends Error{constructor(message="Invalid request"){super(message)}}class Forbidden extends Error{constructor(message="Forbidden"){super(message)}}class NotFound extends Error{constructor(message="Not found"){super(message)}}class NotImplemented extends Error{constructor(message="Not implemented"){super(message)}}class PaymentRequired extends Error{constructor(message="Payment required"){super(message)}}class ServerError extends Error{constructor(message="Server error"){super(message)}}class Teapot extends Error{constructor(message="I'm a teapot"){super(message)}}class Unauthorized extends Error{constructor(message="Unauthorized"){super(message)}}const AccessLevels_PRIVATE="private",AccessLevels_PROTECTED="protected",AccessLevels_PUBLIC="public",RunModes_NORMAL="normal",RunModes_DRY="dry",StatusCodes_OK=200,StatusCodes_BAD_REQUEST=400,StatusCodes_UNAUTHORIZED=401,StatusCodes_PAYMENT_REQUIRED=402,StatusCodes_FORBIDDEN=403,StatusCodes_NOT_FOUND=404,StatusCodes_TEAPOT=418,StatusCodes_SERVER_ERROR=500,StatusCodes_NOT_IMPLEMENTED=501;class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}class ProcedureNotAccessible extends Forbidden{constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`)}}class Segment{#id;#classes=new Map;#procedures=new Map;constructor(id){this.#id=id}get id(){return this.#id}addClass(clazz){return this.#classes.set(clazz.fqn,clazz),this}hasClass(fqn){return void 0!==this.getClass(fqn)}getClass(fqn){return this.#classes.get(fqn)}getClassByImplementation(implementation){return this.getClasses().find((clazz=>clazz.implementation===implementation))}getClasses(){return[...this.#classes.values()]}addProcedure(procedure){return this.#procedures.set(procedure.fqn,procedure),this}hasProcedure(fqn){return this.#procedures.has(fqn)}getProcedure(fqn){return this.#procedures.get(fqn)}getExposedProcedures(){return[...this.#procedures.values()].filter((procedure=>procedure.public||procedure.protected))}}class Class{#fqn;#implementation;constructor(fqn,implementation){this.#fqn=fqn,this.#implementation=implementation}get fqn(){return this.#fqn}get implementation(){return this.#implementation}}class Version{static get DEFAULT(){return new Version(0,0,0)}#major;#minor;#patch;constructor(major=0,minor=0,patch=0){this.#major=major,this.#minor=minor,this.#patch=patch}get major(){return this.#major}get minor(){return this.#minor}get patch(){return this.#patch}equals(version){return this.#major===version.major&&this.#minor===version.minor&&this.#patch===version.patch}greater(version){return this.#major!==version.major?this.#major>version.major:this.#minor!==version.minor?this.#minor>version.minor:this.#patch!==version.patch&&this.#patch>version.patch}less(version){return this.#major!==version.major?this.#major<version.major:this.#minor!==version.minor?this.#minor<version.minor:this.#patch!==version.patch&&this.#patch<version.patch}toString(){return`${this.#major}.${this.#minor}.${this.#patch}`}}class Procedure{#fqn;#implementations=new Map;#latestImplementation;constructor(fqn){this.#fqn=fqn}get fqn(){return this.#fqn}get public(){return[...this.#implementations.values()].some((implementation=>implementation.public))}get protected(){return[...this.#implementations.values()].some((implementation=>implementation.protected))}addImplementation(implementation){return this.#implementations.set(implementation.version,implementation),this.#isNewLatestImplementation(implementation)&&(this.#latestImplementation=implementation),this}#isNewLatestImplementation(implementation){return void 0===this.#latestImplementation||implementation.version.greater(this.#latestImplementation.version)}getImplementation(version){const selectedVersion=this.#selectAvailableVersion(version);return this.#implementations.get(selectedVersion)}#selectAvailableVersion(version){let selectedVersion=Version.DEFAULT;for(const implementationVersion of this.#implementations.keys()){if(implementationVersion.equals(version))return implementationVersion;implementationVersion.greater(version)||selectedVersion.less(implementationVersion)&&(selectedVersion=implementationVersion)}return selectedVersion}}class Implementation{#version;#access;#parameters;#executable;constructor(version,access,parameters,executable){this.#version=version,this.#access=access,this.#parameters=parameters,this.#executable=executable}get version(){return this.#version}get public(){return this.#access===AccessLevels_PUBLIC}get protected(){return this.#access===AccessLevels_PROTECTED}get private(){return this.#access===AccessLevels_PRIVATE}get parameters(){return this.#parameters}get executable(){return this.#executable}}class Parameter{#name;#isOptional;constructor(name,isOptional=!1){this.#name=name,this.#isOptional=isOptional}get name(){return this.#name}get isOptional(){return this.#isOptional}}class NamedParameter extends Parameter{}class DestructuredParameter extends Parameter{#variables;constructor(variables,name,isOptional){super(name??"(anonymous)",isOptional),this.#variables=variables}get variables(){return this.#variables}}class ArrayParameter extends DestructuredParameter{}class ObjectParameter extends DestructuredParameter{}class Request{#fqn;#version;#args;#headers=new Map;#mode;constructor(fqn,version,args,headers,mode){this.#fqn=fqn,this.#version=version,this.#args=args,this.#headers=headers,this.#mode=mode}get fqn(){return this.#fqn}get version(){return this.#version}get args(){return this.#args}get headers(){return this.#headers}get mode(){return this.#mode}clearArguments(){this.#args.clear()}setArgument(name,value){this.#args.set(name,value)}getArgument(name){return this.#args.get(name)}hasArgument(name){return this.#args.has(name)}removeArgument(name){this.#args.delete(name)}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name.toLowerCase(),value)}getHeader(name){return this.#headers.get(name.toLowerCase())}hasHeader(name){return this.#headers.has(name.toLowerCase())}removeHeader(name){this.#headers.delete(name.toLowerCase())}}class Response{#status;#result;#headers;constructor(status,result=void 0,headers=new Map){this.#status=status,this.#result=result,this.#headers=headers}get status(){return this.#status}get result(){return this.#result}set result(value){this.#result=value}get headers(){return this.#headers}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name.toLowerCase(),value)}getHeader(name){return this.#headers.get(name.toLowerCase())}hasHeader(name){return this.#headers.has(name.toLowerCase())}removeHeader(name){this.#headers.delete(name.toLowerCase())}}class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class ArgumentExtractor{extract(parameters,args){const argsCopy=this.#copyArguments(parameters,args),values=[];for(const parameter of parameters){const value=this.#extractArgumentValue(parameter,argsCopy);values.push(value)}if(argsCopy.size>0){const name=argsCopy.keys().next().value;throw new UnknownParameter(name)}return values}#copyArguments(parameters,args){const copy=new Map;for(const[key,value]of args)if(this.#isOptionalArgument(key)){const name=this.#getParameterName(key);!0===this.#containsParameter(parameters,name)&©.set(name,value)}else copy.set(key,value);return copy}#isOptionalArgument(argument){return argument.startsWith("*")}#getParameterName(argument){return argument.substring(1)}#containsParameter(parameters,name){return void 0!==parameters.find((parameter=>parameter.name===name))}#extractArgumentValue(parameter,args,parent){return parameter instanceof NamedParameter?this.#extractNamedArgumentValue(parameter,args,parent):this.#extractDestructedArgumentValue(parameter,args)}#extractNamedArgumentValue(parameter,args,parent){const value=args.get(parameter.name);if(this.#isMissingParameterValue(parameter,value,parent))throw new MissingParameterValue(parameter.name);if(this.#isInvalidRestParameter(parameter,value,parent))throw new InvalidParameterValue(parameter.name);return args.delete(parameter.name),value}#extractDestructedArgumentValue(parameter,args){return parameter instanceof ArrayParameter?this.#extractArrayArgumentValue(parameter,args):this.#extractObjectArgumentValue(parameter,args)}#extractArrayArgumentValue(parameter,args){const values=this.#extractVariableValues(parameter,args);return void 0!==values?Object.values(values):void 0}#extractObjectArgumentValue(parameter,args){return this.#extractVariableValues(parameter,args)}#extractVariableValues(parameter,args){const useIndex=parameter instanceof ArrayParameter,values={},missingValues=[];let containsValues=!1,index=0;for(const variable of parameter.variables){const key=useIndex?index++:variable.name,value=this.#extractArgumentValue(variable,args,parameter);void 0!==value?containsValues=!0:!1===variable.isOptional&&missingValues.push(variable.name),values[key]=value}if(!0===containsValues&&missingValues.length>0)throw new MissingParameterValue(missingValues[0]);return containsValues?values:void 0}#isMissingParameterValue(parameter,value,parent){return void 0===value&&(!0!==parameter.isOptional&&!0!==parent?.isOptional)}#isInvalidRestParameter(parameter,value,parent){return!1!==parameter.name.startsWith("...")&&(void 0===parent&&value instanceof Array==!1||parent instanceof ArrayParameter&&value instanceof Array==!1||parent instanceof ObjectParameter&&value instanceof Object==!1)}}class ErrorConverter{toStatus(error){return error instanceof BadRequest?StatusCodes_BAD_REQUEST:error instanceof Forbidden?StatusCodes_FORBIDDEN:error instanceof NotFound?StatusCodes_NOT_FOUND:error instanceof NotImplemented?StatusCodes_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes_TEAPOT:error instanceof Unauthorized?StatusCodes_UNAUTHORIZED:StatusCodes_SERVER_ERROR}fromStatus(status,message){switch(status){case StatusCodes_BAD_REQUEST:return new BadRequest(message);case StatusCodes_FORBIDDEN:return new Forbidden(message);case StatusCodes_NOT_FOUND:return new NotFound(message);case StatusCodes_NOT_IMPLEMENTED:return new NotImplemented(message);case StatusCodes_PAYMENT_REQUIRED:return new PaymentRequired(message);case StatusCodes_TEAPOT:return new Teapot(message);case StatusCodes_UNAUTHORIZED:return new Unauthorized(message);default:return new ServerError(message)}}}const VERSION_EXPRESSION=/^\d+(?:\.\d+){0,2}$/;class VersionParser{parse(number){if(0===number.trim().length)return Version.DEFAULT;if(!1===VERSION_EXPRESSION.test(number))throw new InvalidVersionNumber(number);const parts=number.split(".");switch(parts.length){case 1:return new Version(Number.parseInt(parts[0]));case 2:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]));default:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]))}}}class ImplementationNotFound extends NotFound{#fqn;#version;constructor(fqn,version){super(`No implementation found for procedure '${fqn}' with version '${version}'`),this.#fqn=fqn,this.#version=version}get fqn(){return this.#fqn}get version(){return this.#version}}class InvalidSegment extends ServerError{constructor(){super("Invalid segment")}}class Application{#segments=new Map;addSegment(segment){this.#segments.set(segment.id,segment)}clearSegments(){this.#segments.clear()}getClassNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getClasses().forEach((clazz=>names.add(clazz.fqn)))}return[...names.values()]}hasClass(fqn){return this.getClassNames().includes(fqn)}getClass(fqn){for(const segment of this.#segments.values())if(segment.hasClass(fqn))return segment.getClass(fqn)}getClassByImplementation(implementation){for(const segment of this.#segments.values()){const clazz=segment.getClassByImplementation(implementation);if(void 0!==clazz)return clazz}}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getExposedProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}}class ExecutionManager{#moduleImporter;#segmentFiles;#argumentConstructor=new ArgumentExtractor;#errorConverter=new ErrorConverter;#application=new Application;constructor(moduleImporter,segmentFiles=[]){this.#moduleImporter=moduleImporter,this.#segmentFiles=segmentFiles}async start(){return this.#loadSegments()}async stop(){return this.#clearSegments()}async loadSegment(filename){const module=await this.#moduleImporter.import(filename);this.addSegment(module.default)}async addSegment(segment){if(segment instanceof Segment==!1)throw new InvalidSegment;this.#application.addSegment(segment)}getClassNames(){return this.#application.getClassNames()}hasClass(fqn){return this.#application.hasClass(fqn)}getClass(fqn){return this.#application.getClass(fqn)}getClassByImplementation(implementation){return this.#application.getClassByImplementation(implementation)}getProcedureNames(){return this.#application.getProcedureNames()}hasProcedure(fqn){return this.#application.hasProcedure(fqn)}getProcedure(fqn){return this.#application.getProcedure(fqn)}async run(request){const implementation=this.#getImplementation(request.fqn,request.version),args=this.#argumentConstructor.extract(implementation.parameters,request.args);return request.mode===RunModes_DRY?new Response(StatusCodes_OK,void 0):this.#runImplementation(request,implementation,args)}async#loadSegments(){await Promise.all(this.#segmentFiles.map((filename=>this.loadSegment(filename))))}#clearSegments(){this.#application.clearSegments()}#getImplementation(fqn,version){const procedure=this.#application.getProcedure(fqn);if(void 0===procedure)throw new ProcedureNotFound(fqn);const implementation=procedure.getImplementation(version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,version.toString());return implementation}async#runImplementation(request,implementation,args){try{const result=await implementation.executable.call(request,...args);return new Response(StatusCodes_OK,result)}catch(error){const status=this.#errorConverter.toStatus(error);return new Response(status,error)}}}class RemoteGateway{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}get trustKey(){}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addWorker(worker){return this.#remote.addWorker(worker.url,worker.getProcedureNames(),worker.trustKey)}removeWorker(worker){return this.#remote.removeWorker(worker.id)}run(request){return this.#remote.run(request)}}class InvalidPath extends Error{#location;constructor(location){super(`Invalid location: ${location}`),this.#location=location}get location(){return this.#location}}class FileNotFound extends Error{#filename;constructor(filename){super(`The file '${filename}' could not be found`),this.#filename=filename}get filename(){return this.#filename}}class File{#location;#type;#content;constructor(location,type,content){this.#location=location,this.#type=type,this.#content=content}get location(){return this.#location}get type(){return this.#type}get content(){return this.#content}get size(){return this.#content.length}}class FileManager{#location;#rootLocation;#fileSystem;constructor(location,fileSystem){this.#location=location,this.#fileSystem=fileSystem,this.#rootLocation=fileSystem.resolve(location)}getAbsoluteLocation(filename){const location=filename.startsWith("/")?filename:this.#fileSystem.join(this.#location,filename),absolutePath=this.#fileSystem.resolve(location);return this.#validateLocation(absolutePath,filename),absolutePath}getRelativeLocation(filename){return this.#fileSystem.relative(this.#location,filename)}async getType(filename){const location=this.getAbsoluteLocation(filename);return await this.#fileSystem.mimeType(location)??"application/octet-stream"}async getContent(filename){const location=this.getAbsoluteLocation(filename);if(!1===await this.#fileSystem.exists(location))throw new FileNotFound(filename);return this.#fileSystem.read(location)}async exists(filename){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.exists(location)}isDirectory(filename){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.isDirectory(location)}async read(filename){const absoluteFilename=this.getAbsoluteLocation(filename),type=await this.getType(absoluteFilename),content=await this.getContent(absoluteFilename);return new File(filename,type,content)}async write(filename,content){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.write(location,content)}async copy(source,destination){const sourceLocation=this.getAbsoluteLocation(source),destinationLocation=this.getAbsoluteLocation(destination);return this.#fileSystem.copy(sourceLocation,destinationLocation)}async delete(filename){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.delete(location)}async filter(pattern){const location=this.getAbsoluteLocation("./");return this.#fileSystem.filter(location,pattern)}#validateLocation(location,filename){if(!1===location.startsWith(this.#rootLocation))throw new InvalidPath(filename)}}class RemoteFilesNotSupported extends Error{constructor(){super("Remote files are not supported")}}class RemoteFileSystem{copy(source,destination){throw new RemoteFilesNotSupported}delete(location){throw new RemoteFilesNotSupported}exists(location){throw new RemoteFilesNotSupported}async filter(location,pattern){return[]}isDirectory(location){throw new RemoteFilesNotSupported}join(...paths){throw new RemoteFilesNotSupported}read(location){throw new RemoteFilesNotSupported}resolve(location){return location}relative(from,to){throw new RemoteFilesNotSupported}mimeType(location){throw new RemoteFilesNotSupported}write(location,content){throw new RemoteFilesNotSupported}}class RemoteFileManager extends FileManager{constructor(location){super(location,new RemoteFileSystem)}}class ModuleNotLoaded extends Error{#url;#reason;constructor(url,reason){super(`Module '${url}' could not be loaded${void 0!==reason?` | ${reason}`:""}`),this.#url=url,this.#reason=reason}get url(){return this.#url}get reason(){return this.#reason}}class ImportManager{#moduleLocator;constructor(moduleLocator){this.#moduleLocator=moduleLocator}async import(filename){const location=this.#moduleLocator.locate(filename);try{return await import(location)}catch(error){const message=error instanceof Error?error.message:String(error);throw new ModuleNotLoaded(location,message)}}}class RemoteModuleLocator{constructor(location){}locate(filename){throw new ModuleNotLoaded(filename,"Remote module loading is not allowed")}}class RemoteImportManager extends ImportManager{constructor(location){super(new RemoteModuleLocator(location))}}class SourcingManager{#fileManager;#importManager;constructor(fileManager,importManager){this.#fileManager=fileManager,this.#importManager=importManager}async filter(...patterns){return(await Promise.all(patterns.map((pattern=>this.#fileManager.filter(pattern))))).flat().map((file=>this.#fileManager.getRelativeLocation(file)))}exists(filename){return this.#fileManager.exists(filename)}read(filename){return this.#fileManager.read(filename)}import(filename){return this.#importManager.import(filename)}}class RemoteSourcingManager extends SourcingManager{constructor(location){super(new RemoteFileManager(location),new RemoteImportManager(location))}}class ClassNotFound extends Error{constructor(name){super(`The class '${name}' could not be found`)}}class InvalidClass extends Error{constructor(name){super(`The class '${name}' is invalid`)}}class NoDeserializerFound extends Error{constructor(type){super(`No deserializer found for value of type '${type}'`)}}class NoSerializerFound extends Error{constructor(type){super(`No serializer found for value of type '${type}'`)}}class Serializer{#serializers=[];addSerializer(serializer){serializer.parent=this,this.#serializers.unshift(serializer)}async serialize(value){const serializer=this.#serializers.find((serializer=>serializer.canSerialize(value)));if(void 0===serializer)throw new NoSerializerFound(typeof value);return serializer.serialize(value)}async deserialize(value){const serializer=this.#serializers.find((serializer=>serializer.canDeserialize(value)));if(void 0===serializer)throw new NoDeserializerFound(typeof value);return serializer.deserialize(value)}}class ParentSerializerNotSet extends Error{constructor(){super("Parent serializer not set")}}class ValueSerializer{#parent;set parent(parent){this.#parent=parent}serializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.serialize(value)}deserializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.deserialize(value)}}class ArraySerializer extends ValueSerializer{canSerialize(value){return value instanceof Array}canDeserialize(value){return value instanceof Array}async serialize(array){const values=[];for(const value of array)values.push(await this.serializeOther(value));return values}async deserialize(array){return Promise.all(array.map((async value=>this.deserializeOther(value))))}}class InvalidBigIntString extends Error{constructor(bigIntString){super(`Invalid BigInt string '${bigIntString}'`)}}class BigIntSerializer extends ValueSerializer{canSerialize(value){return"bigint"==typeof value}canDeserialize(value){const bigInt=value;return bigInt instanceof Object&&!0===bigInt.serialized&&"BigInt"===bigInt.name&&"string"==typeof bigInt.value}async serialize(bigInt){return{serialized:!0,name:"BigInt",value:bigInt.toString()}}async deserialize(object){try{return BigInt(object.value)}catch{throw new InvalidBigIntString(object.value)}}}class InvalidBufferString extends Error{constructor(bufferString){super(`Invalid Buffer string '${bufferString}'`)}}class BufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Buffer}canDeserialize(value){const buffer=value;return buffer instanceof Object&&!0===buffer.serialized&&"Buffer"===buffer.name&&"string"==typeof buffer.base64}async serialize(buffer){return{serialized:!0,name:"Buffer",base64:buffer.toString("base64")}}async deserialize(object){try{return Buffer.from(object.base64,"base64")}catch{throw new InvalidBufferString(object.base64)}}}class ESAlias{#name;#as;constructor(name,as){this.#name=name,this.#as=as}get name(){return this.#name}get as(){return this.#as}toString(){return`${this.#name} as ${this.#as}`}}class ESValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ESArray extends ESValue{}class ESMember{#name;#isStatic;#isPrivate;constructor(name,isStatic=!1,isPrivate=!1){this.#name=name,this.#isStatic=isStatic,this.#isPrivate=isPrivate}get name(){return this.#name}get isStatic(){return this.#isStatic}get isPrivate(){return this.#isPrivate}get isPublic(){return!1===this.#isPrivate}}class ESClass extends ESMember{#parentName;#scope;constructor(name,parentName,scope){super(name),this.#parentName=parentName,this.#scope=scope}get parentName(){return this.#parentName}get scope(){return this.#scope}get members(){return this.#scope.members}get declarations(){return this.#scope.declarations}get functions(){return this.#scope.functions}get getters(){return this.#scope.getters}get setters(){return this.#scope.setters}get generators(){return this.#scope.generators}get readable(){const members=new Map;return this.getters.forEach((getter=>{members.set(getter.name,getter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get writable(){const members=new Map;return this.setters.forEach((setter=>{members.set(setter.name,setter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get callable(){return this.functions.filter((funktion=>funktion.isPublic))}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGetter(name){return this.#scope.getGetter(name)}getSetter(name){return this.#scope.getSetter(name)}getGenerator(name){return this.#scope.getGenerator(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGetter(name){return this.#scope.hasGetter(name)}hasSetter(name){return this.#scope.hasSetter(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}canRead(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return funktion?.isPublic??!1}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ESDeclaration extends ESMember{#identifier;#value;constructor(identifier,value,isStatic=!1,isPrivate=!1){super(identifier.toString(),isStatic,isPrivate),this.#identifier=identifier,this.#value=value}get identifier(){return this.#identifier}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ESDestructuredArray extends ESDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ESDestructuredObject extends ESDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ESExport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}hasMember(name){return this.#members.some((member=>member.as===name))}getMember(name){return this.#members.find((member=>member.as===name))}toString(){const postfix=this.#from?` from '${this.#from}'`:"";return`export { ${this.#members.join(", ")} }${postfix}`}}class ESExpression extends ESValue{}class ESField{#name;#value;constructor(name,value){this.#name=name,this.#value=value}get name(){return this.#name}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESFunction extends ESMember{#parameters;#body;#isAsync;constructor(name,parameters,body,isStatic=!1,isAsync=!1,isPrivate=!1){super(name,isStatic,isPrivate),this.#parameters=parameters,this.#body=body,this.#isAsync=isAsync}get parameters(){return this.#parameters}get body(){return this.#body}get isAsync(){return this.#isAsync}toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}(${parameters.join(", ")}) { ${this.body} }`}}class ESGenerator extends ESFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ESGetter extends ESFunction{toString(){return`get ${super.toString()}`}}class ESImport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}hasMember(name){return this.#members.some((member=>member.as===name))}getMember(name){return this.#members.find((member=>member.as===name))}toString(){return`import { ${this.#members.map((member=>member.toString())).join(", ")} } from '${this.#from}';`}}class ESModule{#scope;constructor(scope){this.#scope=scope}get scope(){return this.#scope}get members(){return this.#scope.members}get exportedMembers(){return this.#filterExported(this.#scope.members)}get imports(){return this.#scope.imports}get exports(){return this.#scope.exports}get declarations(){return this.#scope.declarations}get exportedDeclarations(){return this.#filterExported(this.#scope.declarations)}get functions(){return this.#scope.functions}get exportedFunctions(){return this.#filterExported(this.#scope.functions)}get generators(){return this.#scope.generators}get exportedGenerators(){return this.#filterExported(this.#scope.generators)}get classes(){return this.#scope.classes}get exportedClasses(){return this.#filterExported(this.#scope.classes)}get exported(){const exported=new Map;for(const exportItem of this.exports)for(const alias of exportItem.members){const member=this.getMember(alias.name);void 0!==member&&exported.set(alias.as,member)}return exported}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGenerator(name){return this.#scope.getGenerator(name)}getClass(name){return this.#scope.getClass(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}hasClass(name){return this.#scope.hasClass(name)}getImport(name){return this.imports.find((importItem=>importItem.hasMember(name)))}getImported(name){for(const importItem of this.imports)for(const alias of importItem.members)if(alias.as===name)return this.getMember(alias.name)}isExported(member){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.name===member.name)return!0;return!1}getExport(name){return this.exports.find((exportItem=>exportItem.hasMember(name)))}getExported(name){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.as===name)return this.getMember(alias.name)}#filterExported(members){return members.filter((member=>this.isExported(member)))}}class ESObject extends ESValue{}class ESSetter extends ESFunction{toString(){return`set ${super.toString()}`}}const IMPORT_NAME=ESImport.name,EXPORT_NAME=ESExport.name,DECLARATION_NAME=ESDeclaration.name,FUNCTION_NAME=ESFunction.name,GETTER_NAME=ESGetter.name,SETTER_NAME=ESSetter.name,GENERATOR_NAME=ESGenerator.name,CLASS_NAME=ESClass.name;class ESScope{#members;constructor(members){this.#members=members}get members(){return this.#members}get imports(){return this.#members.filter((member=>member.constructor.name===IMPORT_NAME))}get exports(){return this.#members.filter((member=>member.constructor.name===EXPORT_NAME))}get declarations(){return this.#members.filter((member=>member.constructor.name===DECLARATION_NAME))}get functions(){return this.#members.filter((member=>member.constructor.name===FUNCTION_NAME))}get getters(){return this.#members.filter((member=>member.constructor.name===GETTER_NAME))}get setters(){return this.#members.filter((member=>member.constructor.name===SETTER_NAME))}get generators(){return this.#members.filter((member=>member.constructor.name===GENERATOR_NAME))}get classes(){return this.#members.filter((member=>member.constructor.name===CLASS_NAME))}getMember(name){return this.#members.find((member=>member.name===name))}getDeclaration(name){return this.declarations.find((member=>member.name===name))}getFunction(name){return this.functions.find((member=>member.name===name))}getGetter(name){return this.getters.find((member=>member.name===name))}getSetter(name){return this.setters.find((member=>member.name===name))}getGenerator(name){return this.generators.find((member=>member.name===name))}getClass(name){return this.classes.find((member=>member.name===name))}hasMember(name){return void 0!==this.getMember(name)}hasDeclaration(name){return void 0!==this.getDeclaration(name)}hasFunction(name){return void 0!==this.getFunction(name)}hasGetter(name){return void 0!==this.getGetter(name)}hasSetter(name){return void 0!==this.getSetter(name)}hasGenerator(name){return void 0!==this.getGenerator(name)}hasClass(name){return void 0!==this.getClass(name)}toString(){return this.#members.map((member=>member.toString())).join("\n")}}const Comment={SINGLE:"//",MULTI_START:"/*",MULTI_END:"*/"},Comments=Object.values(Comment);const Punctuation_DOT=".",Punctuation_LEFT_PARENTHESIS="(",Punctuation_RIGHT_PARENTHESIS=")",Punctuation_LEFT_BRACKET="[",Punctuation_RIGHT_BRACKET="]",Punctuation_LEFT_BRACE="{",Punctuation_RIGHT_BRACE="}",Divider={SCOPE:":",SEPARATOR:",",TERMINATOR:";"},Divisions=Object.values(Divider);function isDivider(value){return Divisions.includes(value)}const Empty={UNDEFINED:void 0,NULL:null,STRING:""},Empties=Object.values(Empty);function isEmpty(value){return Empties.includes(value)}const Group={OPEN:Punctuation_LEFT_PARENTHESIS,CLOSE:Punctuation_RIGHT_PARENTHESIS};function isGroup(value){return value===Group.OPEN||value===Group.CLOSE}const Keyword={EXPORT:"export",DEFAULT:"default",CLASS:"class",FUNCTION:"function",CONST:"const",LET:"let",VAR:"var",AS:"as",FROM:"from",IMPORT:"import",GET:"get",SET:"set",EXTENDS:"extends",STATIC:"static",ASYNC:"async",RETURN:"return"},Keywords=Object.values(Keyword);function isKeyword(value){return Keywords.includes(value)}function isNotReserved(value){return value===Keyword.AS||value===Keyword.ASYNC||value===Keyword.FROM||value===Keyword.GET||value===Keyword.SET}const List={OPEN:Punctuation_LEFT_BRACKET,CLOSE:Punctuation_RIGHT_BRACKET};function isList(value){return value===List.OPEN||value===List.CLOSE}const Literals=Object.values({SINGLE:"'",DOUBLE:'"',BACKTICK:"`"});function isLiteral(value){return Literals.includes(value)}const Operator={ADD:"+",ARROW:"=>",ASSIGN:"=",ASSIGN_ADD:"+=",ASSIGN_BITWISE_AND:"&=",ASSIGN_BITWISE_OR:"|=",ASSIGN_DIVIDE:"/=",ASSIGN_LEFT_SHIFT:"<<=",ASSIGN_LOGICAL_AND:"&&=",ASSIGN_LOGICAL_OR:"||=",ASSIGN_MODULO:"%=",ASSIGN_MULTIPLY:"*=",ASSIGN_RIGHT_SHIFT:">>=",ASSIGN_SUBTRACT:"-=",ASSIGN_XOR:"^=",BITWISE_AND:"&",BITWISE_OR:"|",DECREMENT:"--",DIVIDE:"/",EQUAL:"==",EQUAL_STRICT:"===",GREATER:">",GREATER_EQUAL:">=",INCREMENT:"++",LEFT_SHIFT:"<<",LESS:"<",LESS_EQUAL:"<=",LOGICAL_AND:"&&",LOGICAL_OR:"||",MODULO:"%",MULTIPLY:"*",NOT:"!",NOT_EQUAL:"!=",NOT_EQUAL_STRICT:"!==",RIGHT_SHIFT:">>",SUBTRACT:"-",TERNARY:"?",XOR:"^"},Operators=Object.values(Operator);function isOperator(value){return Operators.includes(value)}const Scope={OPEN:Punctuation_LEFT_BRACE,CLOSE:Punctuation_RIGHT_BRACE};function isScope(value){return value===Scope.OPEN||value===Scope.CLOSE}const TokenType={COMMENT:"comment",DIVIDER:"divider",GROUP:"group",IDENTIFIER:"identifier",KEYWORD:"keyword",LIST:"list",LITERAL:"literal",OPERATOR:"operator",REGEX:"regex",SCOPE:"scope",WHITESPACE:"whitespace"},Whitespace={SPACE:" ",TAB:"\t",NEWLINE:"\n",CARRIAGE_RETURN:"\r"},Whitespaces=Object.values(Whitespace);function isWhitespace(value){return Whitespaces.includes(value)}class ItemList{#items;#position;constructor(items){this.#items=items,this.#position=0}get items(){return this.#items}get position(){return this.#position}get size(){return this.#items.length}get eol(){return this.#position>=this.#items.length}get current(){return this.#items[this.#position]}get next(){return this.#items[this.#position+1]}get previous(){return this.#items[this.#position-1]}notAtEnd(){return!1===this.eol}get(index){return this.#items[index]}step(amount=1){return this.#position+=amount,this.current}stepBack(amount=1){return this.#position-=amount,this.current}hasNext(){return this.#position+1<this.#items.length}}class CharList extends ItemList{constructor(code){super(code.split(""))}}class Token{#type;#value;#start;#end;constructor(type,value,start,end){this.#type=type,this.#value=value,this.#start=start,this.#end=end}get type(){return this.#type}get value(){return this.#value}get start(){return this.#start}get end(){return this.#end}isType(type){return this.#type===type}hasValue(value){return this.#value===value}toString(){return`${this.#value}`}}class TokenList extends ItemList{}class Lexer{tokenize(code){const charList=new CharList(code),tokens=[];let last;for(;charList.notAtEnd();){const token=this.#getNextToken(charList,last);if(void 0===token)break;token.isType(TokenType.WHITESPACE)||token.isType(TokenType.COMMENT)?charList.step():(tokens.push(token),this.#isCodeToken(token)&&(last=token),charList.step())}return new TokenList(tokens)}#isCodeToken(token){return!1===[TokenType.WHITESPACE,TokenType.COMMENT].includes(token.type)}#getNextToken(charList,lastToken){const char=charList.current,start=charList.position;if(isWhitespace(char)){const end=charList.position;return new Token(TokenType.WHITESPACE,char,start,end)}if(function(value){return Comments.includes(value)}(char+charList.next)){const value=this.#readComment(charList),end=charList.position;return new Token(TokenType.COMMENT,value,start,end)}if(this.#startsRegex(char,lastToken)){const value=this.#readRegex(charList),end=charList.position;return new Token(TokenType.REGEX,value,start,end)}if(isLiteral(char)){const value=this.#readLiteral(charList),end=charList.position;return new Token(TokenType.LITERAL,value,start,end)}if(isOperator(char)){const value=this.#readOperation(charList),end=charList.position;return new Token(TokenType.OPERATOR,value,start,end)}if(isDivider(char)){const end=charList.position;return new Token(TokenType.DIVIDER,char,start,end)}if(isGroup(char)){const end=charList.position;return new Token(TokenType.GROUP,char,start,end)}if(isScope(char)){const end=charList.position;return new Token(TokenType.SCOPE,char,start,end)}if(isList(char)){const end=charList.position;return new Token(TokenType.LIST,char,start,end)}if(isEmpty(char))return;const value=this.#readIdentifier(charList),type=isKeyword(value)?TokenType.KEYWORD:TokenType.IDENTIFIER,end=charList.position;return new Token(type,value,start,end)}#readComment(charList){const isMulti=charList.current+charList.next===Comment.MULTI_START,terminator=isMulti?Comment.MULTI_END:Whitespace.NEWLINE;let value=isMulti?Comment.MULTI_START:Comment.SINGLE;for(charList.step(2);charList.notAtEnd();){const char=charList.current;if((isMulti?char+charList.next:char)===terminator){charList.step(terminator.length-1);break}value+=char,charList.step()}return isMulti?value+Comment.MULTI_END:value.trim()}#startsRegex(char,lastToken){return char===Operator.DIVIDE&&(void 0===lastToken||([TokenType.OPERATOR,TokenType.DIVIDER,TokenType.KEYWORD].includes(lastToken.type)||[Group.OPEN,List.OPEN].includes(lastToken.value)))}#endsRegex(char){return isWhitespace(char)||char==Punctuation_DOT||!1===this.#isIdentifier(char)}#readRegex(charList){let value=charList.current,closed=!1;for(charList.step();charList.notAtEnd();){const current=charList.current,previous=charList.previous;if(current===Operator.DIVIDE&&"\\"!==previous)closed=!0;else if(!0===closed&&this.#endsRegex(current)){charList.stepBack();break}value+=current,charList.step()}return value}#readLiteral(charList){const identifier=charList.current;let value=identifier,escaped=!1;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===escaped){if(char===identifier){value+=char;break}"\\"===char&&(escaped=!0)}else escaped=!1;value+=char,charList.step()}return value}#isIdentifier(char){return!1===(isEmpty(char)||isWhitespace(char)||isOperator(char)||isLiteral(char)||isDivider(char)||isGroup(char)||isScope(char)||isList(char))}#readIdentifier(charList){let value="";for(;charList.notAtEnd();){const char=charList.current;if(!1===this.#isIdentifier(char)){charList.stepBack();break}value+=char,charList.step()}return value}#readOperation(charList){let value=charList.current;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===isOperator(char)||!1===isOperator(value+char)){charList.stepBack();break}value+=char,charList.step()}return value}}class ExpectedKeyword extends Error{constructor(value,position){super(`Expected keyword '${value}' at position ${position}`)}}class ExpectedToken extends Error{constructor(value,position){super(`Expected token '${value}' at position ${position}`)}}class UnexpectedKeyword extends Error{constructor(keyword,position){super(`Unexpected keyword '${keyword}' at position ${position}`)}}class UnexpectedParseResult extends Error{constructor(expected){super(`The given code does not contain ${expected}`)}}class UnexpectedToken extends Error{constructor(value,position){super(`Unexpected token '${value}' at position ${position}`)}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ESModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ESValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ESImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ESExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ESDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ESMember&&members.push(member)}return new ESScope(members)}#parseNext(tokenList,isAsync=!1){const token=tokenList.current;if(token.isType(TokenType.LITERAL))return this.#parseExpression(tokenList);if(token.isType(TokenType.IDENTIFIER)){const next=tokenList.next;return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD)){if(isNotReserved(token.value)){const next=tokenList.next,nextIsFunction=void 0!==next&&(next.hasValue(Keyword.FUNCTION)||next.hasValue(Group.OPEN));if(token.hasValue(Keyword.ASYNC)&&nextIsFunction)return tokenList.step(),this.#parseNext(tokenList,!0);if(void 0===next||this.#atEndOfStatement(next))return this.#parseExpression(tokenList)}return token.hasValue(Keyword.RETURN)?this.#parseExpression(tokenList):this.#parseMember(tokenList,isAsync)}if(token.isType(TokenType.REGEX))return this.#parseExpression(tokenList);if(token.hasValue(Group.OPEN)){const next=this.#peekAfterBlock(tokenList,Group.OPEN,Group.CLOSE);return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.hasValue(Scope.OPEN))return this.#parseObject(tokenList);if(token.hasValue(List.OPEN))return this.#parseArray(tokenList);if(token.hasValue(Operator.NOT)||token.hasValue(Operator.SUBTRACT))return this.#parseExpression(tokenList);if(!isDivider(token.value))throw new UnexpectedToken(token.value,token.start);tokenList.step()}#parseMember(tokenList,isAsync=!1){const token=tokenList.current;switch(tokenList.step(),token.value){case Keyword.IMPORT:return this.#parseImport(tokenList);case Keyword.EXPORT:return this.#parseExport(tokenList);case Keyword.CLASS:return this.#parseClass(tokenList);case Keyword.FUNCTION:return this.#parseFunction(tokenList,isAsync);case Keyword.VAR:case Keyword.LET:case Keyword.CONST:return this.#parseDeclaration(tokenList,!1,!0);case Keyword.ASYNC:return this.#parseMember(tokenList,!0);default:throw new UnexpectedKeyword(token.value,token.start)}}#parseImport(tokenList){const members=[];let token=tokenList.current;if(token.isType(TokenType.LITERAL))return new ESImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ESImport(members,from)}if(!1===token.hasValue(Scope.OPEN)){const name=token.hasValue(Operator.MULTIPLY)?Operator.MULTIPLY:"default";let as=token.value;token=tokenList.step(),token.hasValue(Keyword.AS)&&(token=tokenList.step(),as=token.value,token=tokenList.step()),members.push(new ESAlias(name,as))}if(token.hasValue(Divider.SEPARATOR)&&(token=tokenList.step()),token.hasValue(Scope.OPEN)){const aliases=this.#parseAliasList(tokenList);members.push(...aliases),token=tokenList.current}if(!1===token.hasValue(Keyword.FROM))throw new ExpectedKeyword(Keyword.FROM,token.start);token=tokenList.step();const from=token.value;return tokenList.step(),new ESImport(members,from)}#parseExport(tokenList){switch(tokenList.current.value){case Keyword.DEFAULT:return tokenList.step(),this.#parseSingleExport(tokenList,!0);case Scope.OPEN:return this.#parseMultiExport(tokenList);default:return this.#parseSingleExport(tokenList,!1)}}#parseSingleExport(tokenList,isDefault){let token=tokenList.current,stepSize=0;var value;token.hasValue(Keyword.ASYNC)&&(token=tokenList.step(),stepSize++),((value=token.value)===Keyword.CLASS||value===Keyword.FUNCTION||value===Keyword.CONST||value===Keyword.LET||value===Keyword.VAR)&&(token=tokenList.step(),stepSize++);const name=this.#isIdentifier(token)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ESAlias(name,as);return new ESExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ESExport(members,from)}#parseAliasList(tokenList){const aliases=[];let token=tokenList.step();for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){token=tokenList.step();continue}const alias=this.#parseAlias(tokenList);aliases.push(alias),token=tokenList.step()}return aliases}#parseAlias(tokenList){let token=tokenList.current;const name=token.value;let as=name;return tokenList.next.hasValue(Keyword.AS)&&(token=tokenList.step(2),as=token.value),new ESAlias(name,as)}#parseDeclaration(tokenList,isStatic,parseMultiple=!1){let identifier,value,token=tokenList.current,isPrivate=!1;return token.hasValue(List.OPEN)?(identifier=this.#parseDestructuredArray(tokenList),token=tokenList.current):token.hasValue(Scope.OPEN)?(identifier=this.#parseDestructuredObject(tokenList),token=tokenList.current):(isPrivate=token.value.startsWith("#"),identifier=isPrivate?token.value.substring(1):token.value,token=tokenList.step()),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1),token=tokenList.current),void 0!==token&&(token.hasValue(Divider.TERMINATOR)?tokenList.step():!0===parseMultiple&&token.hasValue(Divider.SEPARATOR)&&(tokenList.step(),this.#parseDeclaration(tokenList,isStatic,!0))),value instanceof ESGenerator?new ESGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESFunction?new ESFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESClass?new ESClass(identifier.toString(),value.parentName,value.scope):new ESDeclaration(identifier,value,isStatic,isPrivate)}#parseFunction(tokenList,isAsync,isStatic=!1,isGetter=!1,isSetter=!1){let token=tokenList.current,name="",isGenerator=!1,isPrivate=!1;token.hasValue(Operator.MULTIPLY)&&(isGenerator=!0,token=tokenList.step()),this.#isIdentifier(token)&&(isPrivate=token.value.startsWith("#"),name=isPrivate?token.value.substring(1):token.value,token=tokenList.step());const parameters=this.#parseParameters(tokenList,Group.CLOSE);if(token=tokenList.current,!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const body=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return isGenerator?new ESGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ESGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ESSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ESFunction(name,parameters,body,isStatic,isAsync,isPrivate)}#parseArrowFunction(tokenList,isAsync){let parameters,token=tokenList.current;if(token.hasValue(Group.OPEN)?(parameters=this.#parseParameters(tokenList,Group.CLOSE),token=tokenList.current):(parameters=[new ESField(token.value,void 0)],token=tokenList.step())