Best JavaScript code snippet using fast-check-monorepo
CompilationEngine.ts
Source:CompilationEngine.ts
1import JackTokenizer from 'dismantle/Compiler/JackTokenizer';2import Tokenizr from 'tokenizr';3class CompilationEngine {4 private tokenizer: JackTokenizer;5 private output: string[] = [];6 private currentMethod: string[] = [];7 /**8 * Creates a new compilation engine with the given input9 * and output.10 * The next routine called must be compileClass()11 * @param input12 * @param output13 */14 constructor(input: string, output: string) {15 this.tokenizer = new JackTokenizer(input);16 this.compileClass();17 }18 /**19 * 'class' className '{' classVarDec* subroutineDec* '}'20 */21 public compileClass() {22 this.currentMethod.push('compileClass');23 this.output.push('<class>');24 // ========> class <===========25 this.pushKeyword({ keyword: 'class' });26 // ========> className <==========27 this.pushIdentifier();28 // ========> { <==========29 this.pushSymbol({ symbol: '{' });30 // classVarDec, subRoutineDec, or }31 this.tokenizer.advance();32 // both classVarDec and subRoutineDec start with a keyword33 if (this.isKeyword()) {34 let keyword: string;35 // =========> classVarDec* <============36 while (true) {37 // if not keyword, it must be the class end symbol38 // this check is irrelevant for the first iteration39 if (!this.isKeyword()) {40 break;41 }42 keyword = this.tokenizer.keyWord();43 if (keyword !== 'static' && keyword !== 'field') {44 // not a classVarDec, so must be a subRoutineDec, exit the loop45 break;46 }47 this.compileClassVarDec();48 }49 // ============> compileRoutineDec* <===============50 while (true) {51 // if not keyword, it is the class end symbol }, so break off the loop52 if (!this.isKeyword()) {53 break;54 }55 keyword = this.tokenizer.keyWord();56 if (57 keyword !== 'constructor' &&58 keyword !== 'function' &&59 keyword !== 'method'60 ) {61 break;62 }63 this.compileSubroutine();64 }65 }66 // ==========> } <==========67 this.pushSymbol({ symbol: '}', advance: false });68 // </class>69 this.output.push('</class>');70 this.currentMethod.pop();71 }72 /**73 * Compiles a static declaration or a field declaration74 * ('static' | 'field') type varName(',' varName)* ';'75 */76 public compileClassVarDec() {77 this.currentMethod.push('compileClassVarDec');78 this.output.push('<classVarDec>');79 // =======> static | field <=========80 this.pushKeyword({ keywords: ['static', 'field'], advance: false });81 // =======> type <========82 this.tokenizer.advance();83 if (this.isKeyword()) {84 this.pushKeyword({ advance: false });85 } else {86 this.pushIdentifier({ advance: false });87 }88 do {89 // ==========> varName <========90 this.pushIdentifier();91 // ==========> , or ; <=========92 this.pushSymbol({ symbols: [',', ';'] });93 if (this.tokenizer.symbol() === ';') {94 break;95 }96 } while (true);97 // advance over the current classVarDec98 this.tokenizer.advance();99 // </classVarDec>100 this.output.push('</classVarDec>');101 this.currentMethod.pop();102 }103 /**104 * Compiles a complete method, function, or constructor105 * ('constructor' | 'function' | 'method')106 * ('void' | type) subroutineName '(' parameterList ')'107 * subroutineBody108 */109 public compileSubroutine() {110 this.currentMethod.push('compileSubroutine');111 this.output.push('<subroutineDec>');112 // ==========> constructor | function | method <========113 this.pushKeyword({114 advance: false,115 keywords: ['constructor', 'function', 'method'],116 });117 // ========> void | type <=========118 this.tokenizer.advance();119 if (this.isKeyword()) {120 // void or keyword type121 this.pushKeyword({ advance: false });122 } else {123 // user-defined type124 this.pushIdentifier({ advance: false });125 }126 // =======> subroutineName <========127 this.pushIdentifier();128 // =======> ( <========129 this.pushSymbol({ symbol: '(' });130 // =======> parameterList <========131 this.tokenizer.advance();132 this.compileParameterList();133 // =======> ) <=======134 this.pushSymbol({ symbol: ')', advance: false });135 // ========> subroutineBody <=======136 this.tokenizer.advance();137 // this method should advance just over the subroutine138 this.compileSubroutineBody();139 // </subroutineDec>140 this.output.push('</subroutineDec>');141 this.currentMethod.pop();142 }143 /**144 * Compiles a (possibly empty) parameter list, not including the enclosing ()145 * ( (type varName) (',' type varName)* )?146 */147 public compileParameterList() {148 this.currentMethod.push('compileParameterList');149 this.output.push('<parameterList>');150 // parameter list can not start with a symbol, if symbol151 // we are dealing with an empty parameter list, and we have152 // already advanced over it153 if (!this.isSymbol()) {154 while (true) {155 // ========> type <======156 if (this.isKeyword()) {157 // keywords like: this, null, true, false158 this.pushKeyword({ advance: false });159 } else {160 this.pushIdentifier({ advance: false });161 }162 // =========> varName <=========163 this.pushIdentifier();164 // ========> , <===========165 this.tokenizer.advance();166 this.reportTypeError(JackTokenizer.TYPE_SYMBOL);167 const symbol: string = this.tokenizer.symbol();168 if (symbol !== ',') {169 // if not comma, then we have advanced beyond the parameter list170 break;171 }172 // push the comma173 this.pushSymbol({ advance: false });174 // go to next possible parameter175 this.tokenizer.advance();176 }177 }178 this.output.push('</parameterList>');179 this.currentMethod.pop();180 }181 /**182 * compiles a var declaration183 * 'var' type varName (',' varName)* ;184 */185 public compileVarDec() {186 this.currentMethod.push('compileVarDec');187 // <varDec>188 this.output.push('<varDec>');189 // ======> var <========190 this.pushKeyword({ advance: false, keyword: 'var' });191 // ======> type <=======192 this.tokenizer.advance();193 if (this.isKeyword()) {194 this.pushKeyword({ advance: false });195 } else {196 this.pushIdentifier({ advance: false });197 }198 while (true) {199 // ======> varName <=======200 this.pushIdentifier();201 // ======> , or ; <=======202 this.pushSymbol({ symbols: [',', ';'] });203 if (this.tokenizer.symbol() === ';') {204 break;205 }206 }207 // advance over the current varDec208 this.tokenizer.advance();209 // </varDec>210 this.output.push('</varDec>');211 this.currentMethod.pop();212 }213 /**214 * Compiles a sequence of statements, not including the enclosing {}215 */216 public compileStatements() {217 this.currentMethod.push('compileStatements');218 this.output.push('<statements>');219 let keyword: string;220 while (true) {221 // statements stop upon discovery of a symbol, possibly }222 if (!this.isKeyword()) {223 break;224 }225 keyword = this.tokenizer.keyWord();226 if (keyword === 'let') {227 this.compileLet();228 } else if (keyword === 'do') {229 this.compileDo();230 } else if (keyword === 'while') {231 this.compileWhile();232 } else if (keyword === 'if') {233 this.compileIf();234 } else if (keyword === 'return') {235 this.compileReturn();236 } else {237 break;238 }239 }240 this.output.push('</statements>');241 this.currentMethod.pop();242 }243 /**244 * Compiles a let statement245 * 'let' varName ('[' expression ']')? '=' expression ';'246 */247 public compileLet() {248 this.currentMethod.push('compileLet');249 this.output.push('<letStatement>');250 // =======> let <=========251 this.pushKeyword({ advance: false });252 // =======> varName <=========253 this.pushIdentifier();254 // next has to be a symbol, either [ or =255 this.tokenizer.advance();256 // =======> ('[' expression ']')? <=========257 this.reportTypeError(JackTokenizer.TYPE_SYMBOL);258 const symbol: string = this.tokenizer.symbol();259 if (symbol === '[') {260 this.pushSymbol({ symbol: '[', advance: false });261 // expression262 this.tokenizer.advance();263 this.compileExpression();264 // ]265 this.pushSymbol({ symbol: ']', advance: false });266 // advance for =267 this.tokenizer.advance();268 } else if (symbol !== '=') {269 throw Error(`In method compileLet, invalid symbol: ${symbol}`);270 }271 // ============> = <=========272 this.pushSymbol({ symbol: '=', advance: false });273 // ============> expression <=========274 this.tokenizer.advance();275 this.compileExpression();276 // ============> ; <=========277 this.pushSymbol({ symbol: ';', advance: false });278 // advance over this statement279 this.tokenizer.advance();280 this.output.push('</letStatement>');281 this.currentMethod.pop();282 }283 /**284 * Compiles expression285 * term (op term)*286 */287 public compileExpression() {288 this.currentMethod.push('compileExpression');289 this.output.push('<expression>');290 // ============> term <=========291 this.compileTerm();292 // ============> (op term)* <=========293 while (true) {294 if (this.isOperand()) {295 // op296 this.pushSymbol({ advance: false });297 // term298 this.tokenizer.advance();299 this.compileTerm();300 } else {301 break;302 }303 }304 this.output.push('</expression>');305 this.currentMethod.pop();306 }307 /**308 * Compiles a term. This routine is faced with a slight309 * difficulty when trying to decide between some of the310 * alternating parsing rules. Specifically, if the current311 * token is an identifier, the routine must distinguish312 * between a variable, an array entry, and a subroutine313 * call. A single look-ahead token, which may be one of314 * '[', '(' or '.' suffices to distinguish between the315 * three possibilities. Any other token is not part of316 * this term and should not be advanced over.317 * ---------------------318 * integrConstant | stringConstant | keywordConstant |319 * varName | varName '[' expression ']' | subroutineCall |320 * '(' expression ')' | unaryOp term321 */322 public compileTerm() {323 this.currentMethod.push('compileTerm');324 this.output.push('<term>');325 let advance: boolean = true;326 if (this.isIntegerConstant()) {327 // ============> integerConstant <=========328 this.pushIntegerConstant({ advance: false });329 } else if (this.isStringConstant()) {330 // ============> stringConstant <=========331 this.pushStringConstant({ advance: false });332 } else if (this.isKeywordConstant()) {333 // ============> keywordConstants <=========334 this.pushKeyword({ advance: false });335 } else if (this.isSymbol()) {336 if (this.tokenizer.symbol() === '(') {337 // ============> (expression) <=========338 this.pushSymbol({ advance: false });339 this.tokenizer.advance();340 this.compileExpression();341 this.pushSymbol({ symbol: ')', advance: false });342 } else if (this.isUnaryOp()) {343 // ============> unaryOp term <=========344 this.pushSymbol({ advance: false });345 this.tokenizer.advance();346 this.compileTerm();347 advance = false;348 } else {349 throw Error(350 `In compileTerm: Unexpected symbol: ${this.tokenizer.symbol()}`,351 );352 }353 } else if (this.isIdentifier()) {354 // // ============> varName <=========355 // this.pushIdentifier({ advance: false });356 // this.tokenizer.advance();357 // const symbol: string = this.getWord();358 // if (symbol === '[') {359 // // ============> varName[expression] <=========360 // this.pushSymbol({ symbol, advance: false });361 // this.tokenizer.advance();362 // this.compileExpression();363 // this.pushSymbol({ symbol: ']', advance: false });364 // } else if (symbol === '(' || symbol === '.') {365 // // ============> subroutineCall <=========366 // this.pushSymbol({ symbol, advance: false });367 // this.tokenizer.advance();368 // this.compileSubroutineCall();369 // advance = false;370 // } else {371 // // case of just varName, already advaned372 // advance = false;373 // }374 // peek into the next symbol to distnguish between an array expression,375 // a subroutine call, and a plain variable name376 const word: string = this.tokenizer.peek();377 if (word === '[') {378 // ============> varName[expression] <=========379 this.pushIdentifier({380 advance: false,381 });382 this.pushSymbol({ symbol: word });383 this.tokenizer.advance();384 this.compileExpression();385 this.pushSymbol({ symbol: ']', advance: false });386 } else if (word === '(' || word === '.') {387 // ============> subroutineCall <=========388 this.compileSubroutineCall();389 advance = false;390 } else {391 // ============> varName <=========392 this.pushIdentifier({393 advance: false,394 });395 }396 } else {397 throw Error(`In compileTerm: Unknown term: ${this.getWord()}`);398 }399 if (advance) {400 this.tokenizer.advance();401 }402 this.output.push('</term>');403 this.currentMethod.pop();404 }405 /**406 * Compiles a do statement407 * 'do' subroutineCall ';'408 * ---------- subroutineCall -----409 * subroutineName'(' expressionList? ')' |410 * ( className | varName )'.'subroutineName'(' expressionList? ')'411 */412 public compileDo() {413 this.currentMethod.push('compileDo');414 this.output.push('<doStatement>');415 // =======> do <=============416 this.pushKeyword({ advance: false });417 // =======> subroutineCall <=============418 this.tokenizer.advance();419 this.compileSubroutineCall();420 // =======> ; <=============421 this.pushSymbol({ symbol: ';', advance: false });422 // advance over this statement423 this.tokenizer.advance();424 this.output.push('</doStatement>');425 this.currentMethod.pop();426 }427 /**428 * Compiles a possibly empty list of expressions429 * (expression (',' expression)*)?430 */431 public compileExpressionList() {432 this.currentMethod.push('compileExpressionList');433 this.output.push('<expressionList>');434 // if not starting with an identifier, we are dealing435 // with an empty expression list436 if (this.getWord() !== ')') {437 while (true) {438 this.compileExpression();439 this.reportTypeError(JackTokenizer.TYPE_SYMBOL);440 if (this.tokenizer.symbol() === ')') {441 break;442 }443 this.pushSymbol({ symbol: ',', advance: false });444 this.tokenizer.advance();445 }446 }447 this.output.push('</expressionList>');448 this.currentMethod.pop();449 }450 /**451 * Compiles an if statement, possibly with a trailing else clause452 * 'if' '(' expression ')' '{' statements '}'453 * ( 'else' '{' statements '}')?454 */455 public compileIf() {456 this.currentMethod.push('compileIf');457 this.output.push('<ifStatement>');458 // =========> if <==========459 this.pushKeyword({ advance: false });460 // =========> ( <==========461 this.pushSymbol({ symbol: '(' });462 // =========> expression <==========463 this.tokenizer.advance();464 this.compileExpression();465 // =========> ) <==========466 this.pushSymbol({ symbol: ')', advance: false });467 // =========> { <==========468 this.pushSymbol({ symbol: '{' });469 // =========> statements <==========470 // advance to the first keyword471 this.tokenizer.advance();472 this.compileStatements();473 // =========> { <==========474 this.pushSymbol({ symbol: '}', advance: false });475 // =========> else <==========476 this.tokenizer.advance();477 if (this.isKeyword() && this.tokenizer.keyWord() === 'else') {478 this.pushKeyword({ advance: false });479 // =========> { <==========480 this.pushSymbol({ symbol: '{' });481 // =========> statements <==========482 // advance to the first keyword483 this.tokenizer.advance();484 this.compileStatements();485 // =========> { <==========486 this.pushSymbol({ symbol: '}', advance: false });487 // advance one step488 this.tokenizer.advance();489 }490 this.output.push('</ifStatement>');491 this.currentMethod.pop();492 }493 /**494 * Compiles a while statement495 * 'while' '(' expression ')' '{' statements '}'496 */497 public compileWhile() {498 this.currentMethod.push('compileWhile');499 this.output.push('<whileStatement>');500 // =========> while <==========501 this.pushKeyword({ advance: false });502 // =========> ( <==========503 this.pushSymbol({ symbol: '(' });504 // =========> expression <==========505 this.tokenizer.advance();506 this.compileExpression();507 // =========> ) <==========508 this.pushSymbol({ symbol: ')', advance: false });509 // =========> { <==========510 this.pushSymbol({ symbol: '{' });511 // =========> statements <==========512 // advance to the first keyword513 this.tokenizer.advance();514 this.compileStatements();515 // =========> { <==========516 this.pushSymbol({ symbol: '}', advance: false });517 // advance over this statement518 this.tokenizer.advance();519 this.output.push('</whileStatement>');520 this.currentMethod.pop();521 }522 /**523 * Compiles a return statement524 * 'return' expression? ';'525 */526 public compileReturn() {527 this.currentMethod.push('compileReturn');528 this.output.push('<returnStatement>');529 // =========> return <==========530 this.pushKeyword({ advance: false });531 // =========> expression? <==========532 this.tokenizer.advance();533 if (!this.isSymbol()) {534 this.compileExpression();535 }536 // =========> ; <==========537 this.pushSymbol({ symbol: ';', advance: false });538 // advance over current statement539 this.tokenizer.advance();540 this.output.push('</returnStatement>');541 this.currentMethod.pop();542 }543 public getXmlOutput(): string {544 return this.output.join('\n');545 }546 /**547 * subroutineName'(' expressionList? ')' |548 * ( className | varName )'.'subroutineName'(' expressionList? ')'549 */550 private compileSubroutineCall() {551 // =======> subroutineName | className552 // | varName <=============553 this.pushIdentifier({ advance: false });554 this.tokenizer.advance();555 this.reportTypeError(JackTokenizer.TYPE_SYMBOL);556 const symbol: string = this.tokenizer.symbol();557 if (symbol === '.') {558 // ========> . <=======559 this.pushSymbol({ symbol: '.', advance: false });560 // ========> subroutineName <=======561 this.pushIdentifier();562 this.tokenizer.advance();563 }564 // ========> ( <=======565 this.pushSymbol({ symbol: '(', advance: false });566 this.tokenizer.advance();567 // ========> expressionList <=======568 this.compileExpressionList();569 // ========> ) <=======570 this.pushSymbol({ symbol: ')', advance: false });571 // advance over the subroutineCall572 this.tokenizer.advance();573 }574 /**575 * '{' varDec* statements '}'576 */577 private compileSubroutineBody() {578 this.currentMethod.push('compileSubroutineBody');579 this.output.push('<subroutineBody>');580 // =========> { <========581 this.pushSymbol({ symbol: '{', advance: false });582 // =========> varDec* <========583 this.tokenizer.advance();584 do {585 // keyword var has to be detected586 if (!this.isKeyword() || this.getWord() !== 'var') {587 break;588 }589 this.compileVarDec();590 } while (true);591 // =========> statements <========592 this.compileStatements();593 // =========> } <========594 this.pushSymbol({ symbol: '}', advance: false });595 this.tokenizer.advance();596 this.output.push('</subroutineBody>');597 this.currentMethod.pop();598 }599 private isOperand(value?: string): boolean {600 const ops: string[] = ['+', '-', '/', '*', '%', '&', '|', '<', '>', '='];601 if (value !== undefined) {602 return ops.indexOf(value) !== -1;603 }604 const symbol: string = this.tokenizer.symbol();605 return ops.indexOf(symbol) !== -1;606 }607 private isUnaryOp(): boolean {608 const ops: string[] = ['~', '-'];609 const symbol: string = this.tokenizer.symbol();610 return ops.indexOf(symbol) !== -1;611 }612 private isKeywordConstant(): boolean {613 const constants: string[] = ['this', 'null', 'true', 'false'];614 const keyword: string = this.tokenizer.keyWord();615 return constants.indexOf(keyword) !== -1;616 }617 private getCurrentMethod(): string {618 return this.currentMethod[this.currentMethod.length - 1];619 }620 private reportTypeError(expected: number) {621 const found: number = this.tokenizer.tokenType();622 if (found !== expected) {623 throw new Error(624 `In ${this.getCurrentMethod()}:, expected type ${this.translateType(625 expected,626 )}, but found:${this.translateType(627 found,628 )}, and found word: ${this.getWord()}`,629 );630 }631 }632 private reportKeywordError(expected: string) {633 const word: string = this.getWord();634 if (word !== expected) {635 throw new Error(636 `In method: ${this.getCurrentMethod()}, Expected keyword: ${expected}, but found word: ${word}`,637 );638 }639 }640 private reportKeywordsError(expecteds: string[]) {641 const word: string = this.getWord();642 if (expecteds.indexOf(word) === -1) {643 throw new Error(644 `In method: ${this.getCurrentMethod()}, Expected keyword in: ${expecteds}, but found word: ${word}`,645 );646 }647 }648 private reportSymbolError(expected: string) {649 const word: string = this.getWord();650 if (word !== expected) {651 throw new Error(652 `In method: ${this.getCurrentMethod()}, Expected symbol: ${expected}, but found word: ${word}`,653 );654 }655 }656 private reportSymbolsError(expecteds: string[]) {657 const word: string = this.getWord();658 if (expecteds.indexOf(word) === -1) {659 throw new Error(660 `In method: ${this.getCurrentMethod()}, Expected symbol in: ${expecteds}, but found word: ${word}`,661 );662 }663 }664 private pushIntegerConstant(665 { advance }: { advance?: boolean } = { advance: true },666 ) {667 if (advance) {668 this.tokenizer.advance();669 }670 this.reportTypeError(JackTokenizer.TYPE_INT_CONST);671 this.output.push(672 `<integerConstant>${this.tokenizer.intVal()}</integerConstant>`,673 );674 }675 private pushStringConstant(676 { advance }: { advance?: boolean } = { advance: true },677 ) {678 if (advance) {679 this.tokenizer.advance();680 }681 this.reportTypeError(JackTokenizer.TYPE_STRING_CONST);682 this.output.push(683 `<stringConstant>${this.tokenizer.stringVal()}</stringConstant>`,684 );685 }686 private pushSymbol({687 symbol,688 symbols,689 advance = true,690 }: {691 symbol?: string;692 symbols?: string[];693 advance?: boolean;694 }) {695 if (advance) {696 this.tokenizer.advance();697 }698 this.reportTypeError(JackTokenizer.TYPE_SYMBOL);699 if (symbol !== undefined) {700 this.reportSymbolError(symbol);701 }702 if (symbols !== undefined) {703 this.reportSymbolsError(symbols);704 }705 const escapedSymbols: any = {706 '"': '"',707 '&': '&',708 '<': '<',709 '>': '>',710 };711 let value: string = this.tokenizer.symbol();712 if (escapedSymbols[value] !== undefined) {713 value = escapedSymbols[value];714 }715 this.output.push(`<symbol>${value}</symbol>`);716 }717 private pushKeyword({718 keyword,719 keywords,720 advance = true,721 }: {722 keyword?: string;723 keywords?: string[];724 advance?: boolean;725 }) {726 if (advance) {727 this.tokenizer.advance();728 }729 this.reportTypeError(JackTokenizer.TYPE_KEYWORD);730 if (keyword !== undefined) {731 this.reportKeywordError(keyword);732 }733 if (keywords !== undefined) {734 this.reportKeywordsError(keywords);735 }736 this.output.push(`<keyword>${this.tokenizer.keyWord()}</keyword>`);737 }738 private pushIdentifier(739 { advance }: { advance: boolean } = { advance: true },740 ) {741 if (advance) {742 this.tokenizer.advance();743 }744 this.reportTypeError(JackTokenizer.TYPE_IDENTIFIER);745 this.output.push(`<identifier>${this.tokenizer.identifier()}</identifier>`);746 }747 private translateType(type: number): string {748 switch (type) {749 case JackTokenizer.TYPE_KEYWORD:750 return 'KEYWORD';751 case JackTokenizer.TYPE_SYMBOL:752 return 'SYMBOL';753 case JackTokenizer.TYPE_IDENTIFIER:754 return 'IDENTIFIER';755 case JackTokenizer.TYPE_INT_CONST:756 return 'INT_CONST';757 case JackTokenizer.TYPE_STRING_CONST:758 return 'STRING_CONST';759 default:760 return 'UNKNOWN_TYPE';761 }762 }763 private getWord(): any {764 switch (this.tokenizer.tokenType()) {765 case JackTokenizer.TYPE_KEYWORD:766 return this.tokenizer.keyWord();767 case JackTokenizer.TYPE_SYMBOL:768 return this.tokenizer.symbol();769 case JackTokenizer.TYPE_IDENTIFIER:770 return this.tokenizer.identifier();771 case JackTokenizer.TYPE_INT_CONST:772 return this.tokenizer.intVal();773 case JackTokenizer.TYPE_STRING_CONST:774 return this.tokenizer.stringVal();775 default:776 return '';777 }778 }779 private isKeyword(): boolean {780 return this.tokenizer.tokenType() === JackTokenizer.TYPE_KEYWORD;781 }782 private isSymbol(): boolean {783 return this.tokenizer.tokenType() === JackTokenizer.TYPE_SYMBOL;784 }785 private isIdentifier(): boolean {786 return this.tokenizer.tokenType() === JackTokenizer.TYPE_IDENTIFIER;787 }788 private isIntegerConstant(): boolean {789 return this.tokenizer.tokenType() === JackTokenizer.TYPE_INT_CONST;790 }791 private isStringConstant(): boolean {792 return this.tokenizer.tokenType() === JackTokenizer.TYPE_STRING_CONST;793 }794}...
benchmark-poisoning.js
Source:benchmark-poisoning.js
1// @ts-check2import Benchmark from "benchmark";3const NumEntries = 1000;4const PushSymbol = Symbol();5const ApplySymbol = Symbol();6const SafeFunctionPrototype = Function.prototype;7const safeObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;8const safeObjectGetPrototypeOf = Object.getPrototypeOf;9const untouchedPush = Array.prototype.push;10const untouchedApply = Function.prototype.apply;11function onCycle(event) {12 const target = event.target;13 const hz = target.hz; // num runs per second14 const rme = target.stats.rme; // +/-x%15 const n = new Intl.NumberFormat();16 console.log(17 String(target) +18 " â from " +19 n.format((hz * (100 - rme)) / 100) +20 " to " +21 n.format((hz * (100 + rme)) / 100) +22 " ops/sec"23 );24}25function dryRun(pushed) {26 // Try pushing non-numerical value to assess pushing something else does not break optims27 const instance = [];28 instance.push(pushed);29 {30 const instance2 = [];31 instance2[PushSymbol] = untouchedPush;32 instance2[PushSymbol](pushed);33 delete instance2[PushSymbol];34 }35 untouchedPush.call(instance, pushed);36 untouchedPush.apply(instance, [pushed]);37 verySafeApplyBug(untouchedPush, instance, [pushed]);38 verySafeApply(untouchedPush, instance, [pushed]);39 verySafeApplyRetry(untouchedPush, instance, [pushed]);40 verySafeApplyBis(untouchedPush, instance, [pushed]);41 verySafeApplyBis2(untouchedPush, instance, [pushed]);42 safeApply(untouchedPush, instance, [pushed]);43 verySafePush(instance, [pushed]);44 verySafePush2(instance, pushed);45 verySafePush3(instance, pushed);46 verySafePushBuilder(instance, pushed);47 safePush(instance, [pushed]);48 safePush2(instance, pushed);49 safePushBuilder(instance, pushed);50 safePushBuilder2(instance, pushed);51 safePushBuilder3(instance, pushed);52}53function run() {54 const allBenchmarks = [55 new Benchmark("direct push", () => {56 const instance = [];57 for (let i = 0; i !== NumEntries; ++i) {58 instance.push(i);59 }60 }),61 new Benchmark("direct [PushSymbol]", () => {62 const instance = [];63 instance[PushSymbol] = untouchedPush;64 for (let i = 0; i !== NumEntries; ++i) {65 instance[PushSymbol](i);66 }67 delete instance[PushSymbol];68 }),69 new Benchmark("direct renewed [PushSymbol]", () => {70 const instance = [];71 for (let i = 0; i !== NumEntries; ++i) {72 instance[PushSymbol] = untouchedPush;73 instance[PushSymbol](i);74 delete instance[PushSymbol];75 }76 }),77 new Benchmark("call push", () => {78 const instance = [];79 for (let i = 0; i !== NumEntries; ++i) {80 untouchedPush.call(instance, i);81 }82 }),83 new Benchmark("apply push", () => {84 const instance = [];85 for (let i = 0; i !== NumEntries; ++i) {86 untouchedPush.apply(instance, [i]);87 }88 }),89 new Benchmark("'very safe' apply push (getown) (((bug)))", () => {90 const instance = [];91 for (let i = 0; i !== NumEntries; ++i) {92 verySafeApplyBug(untouchedPush, instance, [i]);93 }94 }),95 new Benchmark("'very safe' apply push (getown)", () => {96 const instance = [];97 for (let i = 0; i !== NumEntries; ++i) {98 verySafeApply(untouchedPush, instance, [i]);99 }100 }),101 new Benchmark("'very safe' apply push (getown/hasown)", () => {102 const instance = [];103 for (let i = 0; i !== NumEntries; ++i) {104 verySafeApplyRetry(untouchedPush, instance, [i]);105 }106 }),107 new Benchmark("'very safe' apply push (try/catch)", () => {108 const instance = [];109 for (let i = 0; i !== NumEntries; ++i) {110 verySafeApplyBis(untouchedPush, instance, [i]);111 }112 }),113 new Benchmark("'very safe' apply push (try/catch apply)", () => {114 const instance = [];115 for (let i = 0; i !== NumEntries; ++i) {116 verySafeApplyBis2(untouchedPush, instance, [i]);117 }118 }),119 new Benchmark("'safe' apply push", () => {120 const instance = [];121 for (let i = 0; i !== NumEntries; ++i) {122 safeApply(untouchedPush, instance, [i]);123 }124 }),125 new Benchmark("'very safe' direct push (try/catch)", () => {126 const instance = [];127 for (let i = 0; i !== NumEntries; ++i) {128 verySafePush(instance, [i]);129 }130 }),131 new Benchmark("'very safe' direct push (try/catch)(varargs)", () => {132 const instance = [];133 for (let i = 0; i !== NumEntries; ++i) {134 verySafePush2(instance, i);135 }136 }),137 new Benchmark("'very safe' direct push (try/catch push)(varargs)", () => {138 const instance = [];139 for (let i = 0; i !== NumEntries; ++i) {140 verySafePush3(instance, i);141 }142 }),143 new Benchmark(144 "'very safe' direct push builder (try/catch push)(varargs)",145 () => {146 const instance = [];147 for (let i = 0; i !== NumEntries; ++i) {148 verySafePushBuilder(instance, i);149 }150 }151 ),152 new Benchmark("'safe' direct push", () => {153 const instance = [];154 for (let i = 0; i !== NumEntries; ++i) {155 safePush(instance, [i]);156 }157 }),158 new Benchmark("'safe' direct push (varargs)", () => {159 const instance = [];160 for (let i = 0; i !== NumEntries; ++i) {161 safePush2(instance, i);162 }163 }),164 new Benchmark("'safe' direct push builder (varargs)", () => {165 const instance = [];166 for (let i = 0; i !== NumEntries; ++i) {167 safePushBuilder(instance, i);168 }169 }),170 new Benchmark("'safe' direct push builder (extractor)(varargs)", () => {171 const instance = [];172 for (let i = 0; i !== NumEntries; ++i) {173 safePushBuilder2(instance, i);174 }175 }),176 new Benchmark("'safe' direct push builder (extractor all)(varargs)", () => {177 const instance = [];178 for (let i = 0; i !== NumEntries; ++i) {179 safePushBuilder3(instance, i);180 }181 }),182 ];183 Benchmark.invoke(allBenchmarks, { name: "run", queued: true, onCycle });184}185// Others186function safeApplyHacky(f, instance, args) {187 f[ApplySymbol] = untouchedApply;188 const out = f[ApplySymbol](instance, args);189 delete f[ApplySymbol];190 return out;191}192function verySafeApplyBug(f, instance, args) {193 const descApply = safeObjectGetOwnPropertyDescriptor(f, "apply");194 if (descApply !== undefined && descApply.value === untouchedApply) {195 return f.apply(instance, args);196 }197 return safeApplyHacky(f, instance, args);198}199function verySafeApply(f, instance, args) {200 const fPrototype = safeObjectGetPrototypeOf(f);201 if (202 // Function.prototype is not writable so it will never be dropped nor changed,203 fPrototype === SafeFunctionPrototype &&204 // on the other hand Function.prototype.apply or f.apply can be edited!205 safeObjectGetOwnPropertyDescriptor(f, "apply") === undefined &&206 safeObjectGetOwnPropertyDescriptor(SafeFunctionPrototype, "apply").value ===207 untouchedApply208 ) {209 return f.apply(instance, args);210 }211 return safeApplyHacky(f, instance, args);212}213function verySafeApplyRetry(f, instance, args) {214 if (215 // Function.prototype is not writable so it will never be dropped nor changed,216 f instanceof Function && // tried instanceof instead of getPrototypeOf (but more buggy as it traverses the whole prototype chain)217 // on the other hand Function.prototype.apply or f.apply can be edited!218 !f.hasOwnProperty("apply") && // tried hasOwnProperty instead of getOwnPropertyDescriptor (but would need safe apply to run too)219 safeObjectGetOwnPropertyDescriptor(SafeFunctionPrototype, "apply").value ===220 untouchedApply221 ) {222 return f.apply(instance, args);223 }224 return safeApplyHacky(f, instance, args);225}226function safeExtract(instance, name) {227 try {228 return instance[name];229 } catch (err) {230 return undefined;231 }232}233function safeExtractApply(instance) {234 try {235 return instance.apply;236 } catch (err) {237 return undefined;238 }239}240function safeExtractPush(instance) {241 try {242 return instance.push;243 } catch (err) {244 return undefined;245 }246}247// Not as safe as the other one as it may be tricked by users248// overriding the apply function in a nasty way making it throw halp of the time249function verySafeApplyBis(f, instance, args) {250 if (safeExtract(f, "apply") === untouchedApply) {251 return f.apply(instance, args);252 }253 return safeApplyHacky(f, instance, args);254}255function verySafeApplyBis2(f, instance, args) {256 if (safeExtractApply(f) === untouchedApply) {257 return f.apply(instance, args);258 }259 return safeApplyHacky(f, instance, args);260}261function safeApply(f, instance, args) {262 if (f.apply === untouchedApply) {263 return f.apply(instance, args);264 }265 return safeApplyHacky(f, instance, args);266}267function verySafePush(instance, args) {268 if (safeExtract(instance, "push") === untouchedPush) {269 return instance.push(...args);270 }271 return verySafeApplyBis(untouchedPush, instance, args);272}273function verySafePush2(instance, ...args) {274 if (safeExtract(instance, "push") === untouchedPush) {275 return instance.push(...args);276 }277 return verySafeApplyBis(untouchedPush, instance, args);278}279function verySafePush3(instance, ...args) {280 if (safeExtractPush(instance) === untouchedPush) {281 return instance.push(...args);282 }283 return verySafeApplyBis(untouchedPush, instance, args);284}285function verySafeBuilder(CType, name) {286 const untouched = CType.prototype[name];287 function safeExtract(instance) {288 try {289 return instance[name];290 } catch (err) {291 return undefined;292 }293 }294 function verySafe(instance, ...args) {295 if (safeExtract(instance) === untouched) {296 return instance[name](...args);297 }298 return verySafeApplyBis(untouched, instance, args);299 }300 return verySafe;301}302const verySafePushBuilderUnused = verySafeBuilder(Array, "concat");303verySafePushBuilderUnused([], []);304const verySafePushBuilderUnused2 = verySafeBuilder(String, "split");305verySafePushBuilderUnused2("a,b,c", ",");306const verySafePushBuilder = verySafeBuilder(Array, "push");307function safePush(instance, args) {308 if (instance.push === untouchedPush) {309 return instance.push(...args);310 }311 return safeApply(untouchedPush, instance, args);312}313function safePush2(instance, ...args) {314 if (instance.push === untouchedPush) {315 return instance.push(...args);316 }317 return safeApply(untouchedPush, instance, args);318}319function safeBuilder(CType, name) {320 const untouched = CType.prototype[name];321 function safe(instance, ...args) {322 if (instance[name] === untouched) {323 return instance[name](...args);324 }325 return safeApply(untouched, instance, args);326 }327 return safe;328}329const safePushBuilderUnused = safeBuilder(Array, "concat");330safePushBuilderUnused([], []);331const safePushBuilderUnused2 = safeBuilder(String, "split");332safePushBuilderUnused2("a,b,c", ",");333const safePushBuilder = safeBuilder(Array, "push");334function safeBuilder2(CType, name, extractor) {335 const untouched = CType.prototype[name];336 function safe(instance, ...args) {337 if (extractor(instance) === untouched) {338 return instance[name](...args);339 }340 return safeApply(untouched, instance, args);341 }342 return safe;343}344const safePushBuilder2 = safeBuilder2(Array, "push", (i) => i.push);345function safeBuilder3(CType, name, extractor) {346 const untouched = extractor(CType.prototype);347 function safe(instance, ...args) {348 if (extractor(instance) === untouched) {349 return instance[name](...args);350 }351 return safeApply(untouched, instance, args);352 }353 return safe;354}355const safePushBuilder3 = safeBuilder3(Array, "push", (i) => i.push);356dryRun("i");357dryRun(["i"]);358dryRun(() => {});...
calculator.js
Source:calculator.js
1var current_input = [];2var calculator = new MathSolver3var RESULT_MSG = "Enter an expression and then press the '=' button (or hit ENTER on your keyboard) to calculate result";4var INPUT_MSG = "Example: 1 1 +";5$(document).ready(function() {6 // Clean game state7 clear();8});9function refreshDisplay() {10 current_input !== "" 11 ? $('#display').text(current_input.join('')) 12 : $('#display').text("No input yet.");13}14function pushSymbol(x) {15 current_input.push(x);16 refreshDisplay();17}18function popSymbol() {19 current_input.pop();20 refreshDisplay();21}22function evalResult() {23 if (current_input.length > 0)24 $('#result').text(calculator.solvePostfix(current_input.join('')));25 refreshDisplay();26} 27function clear(){28 current_input = [];29 refreshDisplay();30 $('#display').html('<span class="greyed_out">' + INPUT_MSG + '</span>');31 $('#result').html('<span class="greyed_out">' + RESULT_MSG + '</span>');32}33/* Number buttons */34$('.number').on("click", function() {35 pushSymbol($(this).attr("value"))36});37/* Operators */38$('.operator').on("click", function() {39 pushSymbol($(this).attr("value"))40});41/* Other buttons */42$('#button-equal').on("click", function() {43 evalResult();44});45$('#button-space').on("click", function() {46 pushSymbol(' ');47});48$('#button-clear').on("click", function() {49 clear();50});51/* Keyboard Control */52var validKeys = ['0','1','2','3','4','5','6','7','8','9','+','-','*','/','^', ' ']53$(document).keyup(function(event) {54 var isValid;55 (validKeys.indexOf(event.key) !== -1) ? isValid = true : isValid = false;56 if (event.key === 'Enter') {57 evalResult();58 } else if (event.key === "Backspace" || event.key === "Delete") {59 popSymbol();60 } else if (isValid) {61 pushSymbol(event.key);62 } else if (event.key === 'c') {63 clear(); // Do nothing for invalid keyboard input64 }65});66function MathSolver() {67 this.solvePostfix = function(postfix) {68 var resultStack = []; // Store a list of tokens 69 postfix = postfix.split(" ");70 for(var i = 0; i < postfix.length; i++) {71 if(postfix[i].isNumeric()){72 resultStack.push(postfix[i]);73 } else {74 var a = resultStack.pop();75 var b = resultStack.pop();76 switch(postfix[i]){77 case "+":78 resultStack.push(parseInt(a) + parseInt(b));79 break;80 case "-":81 resultStack.push(parseInt(a) - parseInt(b));82 break;83 case "*":84 resultStack.push(parseInt(a) * parseInt(b));85 break;86 case "/":87 resultStack.push(parseInt(a) / parseInt(b));88 break;89 case "^":90 resultStack.push(Math.pow(parseInt(b), parseInt(a)));91 break;92 }93 }94 }95 if(resultStack.length > 1) {96 return "error";97 } else {98 return resultStack.pop();99 }100 }101}102String.prototype.isNumeric = function() {103 return !isNaN(parseFloat(this)) && isFinite(this);...
Using AI Code Generation
1const { PushSymbol } = require('fast-check-monorepo');2console.log(PushSymbol);3const { PushSymbol } = require('fast-check-monorepo');4console.log(PushSymbol);5const { PushSymbol } = require('fast-check-monorepo');6console.log(PushSymbol);7const { PushSymbol } = require('fast-check-monorepo');8console.log(PushSymbol);9const { PushSymbol } = require('fast-check-monorepo');10console.log(PushSymbol);11const { PushSymbol } = require('fast-check-monorepo');12console.log(PushSymbol);13const { PushSymbol } = require('fast-check-monorepo');14console.log(PushSymbol);15const { PushSymbol } = require('fast-check-monorepo');16console.log(PushSymbol);17const { PushSymbol } = require('fast-check-monorepo');18console.log(PushSymbol);19const { PushSymbol } = require('fast-check-monorepo');20console.log(PushSymbol);21const { PushSymbol } = require('fast-check-monorepo');22console.log(PushSymbol);23const { PushSymbol } = require('fast-check-monorepo');24console.log(PushSymbol);25const { PushSymbol } = require('fast-check-monorepo');26console.log(Push
Using AI Code Generation
1const fc = require('fast-check');2const { PushSymbol } = require('@fast-check/push-symbol');3const { PushSymbol } = require('@fast-check/push-symbol');4fc.assert(5 fc.property(fc.integer(), fc.integer(), (a, b) => {6 fc.pre(a !== b);7 return a + b !== b + a;8 })9);10const fc = require('fast-check');11const { PushSymbol } = require('@fast-check/push-symbol');12const { PushSymbol } = require('@fast-check/push-symbol');13fc.assert(14 fc.property(fc.integer(), fc.integer(), (a, b) => {15 fc.pre(a !== b);16 return a + b !== b + a;17 })18);19const fc = require('fast-check');20const { PushSymbol } = require('@fast-check/push-symbol');21const { PushSymbol } = require('@fast-check/push-symbol');22fc.assert(23 fc.property(fc.integer(), fc.integer(), (a, b) => {24 fc.pre(a !== b);25 return a + b !== b + a;26 })27);28const fc = require('fast-check');29const { PushSymbol } = require('@fast-check/push-symbol');30const { PushSymbol } = require('@fast-check/push-symbol');31fc.assert(32 fc.property(fc.integer(), fc.integer(), (a, b) => {33 fc.pre(a !== b);34 return a + b !== b + a;35 })36);37const fc = require('fast-check');38const { PushSymbol } =
Using AI Code Generation
1const { PushSymbol } = require('fast-check-monorepo');2const { check, property } = require('fast-check');3describe('A test', () => {4 it('should pass', () => {5 check(6 property(PushSymbol('mySymbol'), (s) => {7 return true;8 })9 );10 });11});12 at Object.PushSymbol (node_modules/fast-check-monorepo/lib/src/arbitrary/PushSymbol.js:14:27)13 at Object.<anonymous> (test.js:7:33)14const { PushSymbol } = require('fast-check-monorepo');15const { check, property } = require('fast-check');16describe('A test', () => {17 it('should pass', () => {18 check(19 property(PushSymbol('mySymbol')(), (s) => {20 return true;21 })22 );23 });24});25 ✓ should pass (7 ms)
Using AI Code Generation
1const { PushSymbol } = require('fast-check-monorepo');2const x = new PushSymbol();3x.PushSymbol('test');4console.log(x);5const { PushSymbol } = require('../dist');6const x = new PushSymbol();7x.PushSymbol('test');8console.log(x);9const { PushSymbol } = require('fast-check-monorepo');10const x = new PushSymbol();11x.PushSymbol('test');12console.log(x);13const { PushSymbol } = require('../dist');14const x = new PushSymbol();15x.PushSymbol('test');16console.log(x);17const { PushSymbol } = require('fast-check-monorepo');18const x = new PushSymbol();19x.PushSymbol('test');20console.log(x);21const { PushSymbol } = require('../dist');22const x = new PushSymbol();23x.PushSymbol('test');24console.log(x);25const { PushSymbol } = require('fast-check-monorepo');26const x = new PushSymbol();27x.PushSymbol('test');28console.log(x);29const { PushSymbol } = require('../dist');30const x = new PushSymbol();31x.PushSymbol('test');32console.log(x);33const { PushSymbol } = require('fast-check-monorepo');34const x = new PushSymbol();35x.PushSymbol('test');36console.log(x);37const { PushSymbol } = require('../dist');38const x = new PushSymbol();39x.PushSymbol('test');40console.log(x);41const { PushSymbol } = require('
Using AI Code Generation
1const { check, property, pushSymbol } = require("fast-check");2pushSymbol("test");3check(property([1, 2, 3], (array) => array.length === 3), {4});5const { check, property, pushSymbol } = require("fast-check");6pushSymbol("test2");7check(property([1, 2, 3], (array) => array.length === 3), {8});9const { check, property, pushSymbol } = require("fast-check");10pushSymbol("test3");11check(property([1, 2, 3], (array) => array.length === 3), {12});13const { check, property, pushSymbol } = require("fast-check");14pushSymbol("test4");15check(property([1, 2, 3], (array) => array.length === 3), {16});17const { check, property, pushSymbol } = require("fast-check");18pushSymbol("test5");19check(property([1, 2, 3], (array) => array.length === 3), {20});21const { check, property, pushSymbol } = require("fast-check");22pushSymbol("test6");23check(property([1, 2, 3], (array) => array.length === 3), {24});25const { check, property, pushSymbol } = require("fast-check");26pushSymbol("test7");27check(property([1, 2, 3], (array) => array.length === 3), {28});
Using AI Code Generation
1const fc = require('fast-check');2const { PushSymbol } = require('fast-check/lib/types/property/Property.generic');3const arb = fc.array(fc.integer());4const prop = (xs) => xs.length > 0;5const p = new PushSymbol();6const pProp = prop[p];7const pArb = arb[p];8console.log(pProp);9console.log(pArb);10{11 "scripts": {12 },13 "dependencies": {14 }15}16const fc = require('fast-check');17const { PushSymbol } = require('fast-check/lib/types/property/Property.generic');18const arb = fc.array(fc.integer());19const prop = (xs) => xs.length > 0;20const p = new PushSymbol();21const pProp = prop[p];22const pArb = arb[p];23console.log(pProp);24console.log(pArb);25{26 "scripts": {27 },28 "dependencies": {29 }30}31const fc = require('fast
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!