stencil-scope.js (4544B)
1 const optionsFull = { 2 fileName: "compileToStencil-DATA.js", 3 lineNumber: 1, 4 eagerDelazificationStrategy: "ParseEverythingEagerly", 5 }; 6 7 const optionsLazy = { 8 fileName: "compileToStencil-DATA.js", 9 lineNumber: 1, 10 eagerDelazificationStrategy: "OnDemandOnly", 11 }; 12 13 const optionsLazyCache = { 14 fileName: "compileToStencil-DATA.js", 15 lineNumber: 1, 16 eagerDelazificationStrategy: "ConcurrentDepthFirst", 17 }; 18 19 const optionsLazyCache2 = { 20 fileName: "compileToStencil-DATA.js", 21 lineNumber: 1, 22 eagerDelazificationStrategy: "ConcurrentLargeFirst", 23 }; 24 25 let result = 0; 26 27 function testMainThread(script_str) { 28 const stencil = compileToStencil(script_str, optionsFull); 29 result = evalStencil(stencil, optionsFull); 30 assertEq(result, 1); 31 } 32 33 function testMainThreadDelazifyAll(script_str) { 34 if (isLcovEnabled()) { 35 // Code-coverage implies forceFullParse = true, and as such it cannot be 36 // used while testing to incrementally delazify. 37 return; 38 } 39 const stencil = compileToStencil(script_str, optionsLazy); 40 result = evalStencil(stencil, optionsLazy); 41 assertEq(result, 1); 42 } 43 44 function testMainThreadCacheAll(script_str) { 45 if (isLcovEnabled() || helperThreadCount() === 0) { 46 // Code-coverage implies forceFullParse = true, and as such it cannot be 47 // used while testing to incrementally delazify. 48 // Similarly, concurrent delazification requires off-threads processing. 49 return; 50 } 51 const stencil = compileToStencil(script_str, optionsLazyCache); 52 result = evalStencil(stencil, optionsLazyCache); 53 assertEq(result, 1); 54 } 55 56 function testMainThreadCacheAll2(script_str) { 57 if (isLcovEnabled() || helperThreadCount() === 0) { 58 // Code-coverage implies forceFullParse = true, and as such it cannot be 59 // used while testing to incrementally delazify. 60 // Similarly, concurrent delazification requires off-threads processing. 61 return; 62 } 63 const stencil = compileToStencil(script_str, optionsLazyCache2); 64 result = evalStencil(stencil, optionsLazyCache2); 65 assertEq(result, 1); 66 } 67 68 function testOffThread(script_str) { 69 const job = offThreadCompileToStencil(script_str, optionsFull); 70 const stencil = finishOffThreadStencil(job); 71 result = evalStencil(stencil, optionsFull); 72 assertEq(result, 1); 73 } 74 75 // These patches are meant to wrap the inner code given as argument into one 76 // kind of scope. The freeVars specify one way to retrieve the variable name 77 // added in this process if any. 78 const scopeCases = [ 79 { code: inner => `{ ${inner} }`, freeVars: [] }, 80 { code: inner => `{ var v = 1; ${inner} }`, freeVars: ["v"] }, 81 { code: inner => `{ let l = 1; ${inner} }`, freeVars: ["l"] }, 82 { code: inner => `{ const c = 1; ${inner} }`, freeVars: ["c"] }, 83 { code: inner => `with ({ p: 1 }) { ${inner} }`, freeVars: ["p"], 84 inClass: false }, 85 { code: inner => `(a => { ${inner} })(1)`, freeVars: ["a"] }, 86 { code: inner => `function fun(a) { ${inner} }; fun(1)`, freeVars: ["a"], 87 inClass: false}, 88 { code: inner => `try { ${inner} } catch(unused) { }`, freeVars: [] }, 89 { code: inner => `try { throw 1; } catch(t) { ${inner} }`, freeVars: ["t"] }, 90 { code: inner => `{ class C { #m = 1; constructor() { ${inner} }}; new C() }`, 91 freeVars: ["this.#m"], isClass: true }, 92 ]; 93 94 // This function is used to generate code which mostly exercise the various kind 95 // of scopes to cover ScopeContext class in CompilationStencil.h 96 function generateCode(seed) { 97 let start = inner => ` 98 ${inner}; 99 result 100 `; 101 102 let prog = [start]; 103 let freeVars = ["1"]; 104 let inClass = false; 105 106 while (seed >= freeVars.length) { 107 let index = seed % scopeCases.length; 108 seed = (seed / scopeCases.length) | 0; 109 let scope = scopeCases[index]; 110 if (inClass && !(scope.inClass ?? false)) { 111 // Skip illegal code (non-strict) or code which might not accept 112 // this to work. 113 continue; 114 } 115 inClass ||= scope.isClass ?? false; 116 prog.push(scope.code); 117 freeVars = freeVars.concat(scope.freeVars); 118 } 119 120 let name = freeVars[seed]; 121 return prog.reduceRight((inner, f) => f(inner), `result = ${name}`); 122 } 123 124 for (let s = 0; s < 3000; s++) { 125 let code = generateCode(s); 126 // console.log(s, ":", code); 127 testMainThread(code); 128 testMainThreadDelazifyAll(code); 129 testMainThreadCacheAll(code); 130 testMainThreadCacheAll2(code); 131 if (helperThreadCount() > 0) { 132 testOffThread(code); 133 } 134 }