envChain_frame-evalWithBindings.js (5419B)
1 // Verify the environment chain for Debugger.Frame described in 2 // js/src/vm/EnvironmentObject.h. 3 4 const g = newGlobal({ newCompartment: true }); 5 const dbg = Debugger(g); 6 7 dbg.onEnterFrame = frame => { 8 if (frame.script.displayName !== "target") { 9 return; 10 } 11 dbg.onEnterFrame = () => {}; 12 13 const bindings = { 14 bindings_prop: 50, 15 16 bindings_prop_var: 61, 17 bindings_prop_lexical: 71, 18 bindings_prop_unqualified: 81, 19 }; 20 21 const {envs, vars} = JSON.parse(frame.evalWithBindings(` 22 var qualified = 10; 23 unqualified = 20; 24 let lexical = 30; 25 this.prop = 40; 26 27 var bindings_prop_var = 60; 28 let bindings_prop_lexical = 70; 29 bindings_prop_unqualified = 80; 30 31 const vars = { 32 bindings_prop_var, 33 bindings_prop_lexical, 34 bindings_prop_unqualified, 35 }; 36 37 const envs = []; 38 let env = getInnerMostEnvironmentObject(); 39 while (env) { 40 envs.push({ 41 type: getEnvironmentObjectType(env) || "*global*", 42 qualified: !!Object.getOwnPropertyDescriptor(env, "qualified"), 43 unqualified: !!Object.getOwnPropertyDescriptor(env, "unqualified"), 44 lexical: !!Object.getOwnPropertyDescriptor(env, "lexical"), 45 prop: !!Object.getOwnPropertyDescriptor(env, "prop"), 46 bindings_prop: !!Object.getOwnPropertyDescriptor(env, "bindings_prop"), 47 48 bindings_prop_var: !!Object.getOwnPropertyDescriptor(env, "bindings_prop_var"), 49 bindings_prop_var_value: Object.getOwnPropertyDescriptor(env, "bindings_prop_var")?.value, 50 bindings_prop_lexical: !!Object.getOwnPropertyDescriptor(env, "bindings_prop_lexical"), 51 bindings_prop_lexical_value: Object.getOwnPropertyDescriptor(env, "bindings_prop_lexical")?.value, 52 bindings_prop_unqualified: !!Object.getOwnPropertyDescriptor(env, "bindings_prop_unqualified"), 53 bindings_prop_unqualified_value: Object.getOwnPropertyDescriptor(env, "bindings_prop_unqualified")?.value, 54 }); 55 56 env = getEnclosingEnvironmentObject(env); 57 } 58 JSON.stringify({envs, vars}); 59 `, bindings).return); 60 61 assertEq(vars.bindings_prop_var, 60, 62 "qualified var should read the value set by the declaration"); 63 assertEq(vars.bindings_prop_lexical, 70, 64 "lexical should read the value set by the declaration"); 65 assertEq(vars.bindings_prop_unqualified, 80, 66 "unqualified name should read the value set by the assignment"); 67 68 assertEq(bindings.bindings_prop_var, 61, 69 "the original bindings property must not be overwritten for var"); 70 assertEq(bindings.bindings_prop_lexical, 71, 71 "the original bindings property must not be overwritten for lexical"); 72 assertEq(bindings.bindings_prop_unqualified, 81, 73 "the original bindings property must not be overwritten for unqualified"); 74 75 assertEq(envs.length, 4); 76 77 let i = 0, env; 78 79 // NOTE: lexical is optimized and uses frame slot, even if it conflicts with 80 // bindings object properties. 81 82 env = envs[i]; i++; 83 assertEq(env.type, "WithEnvironmentObject"); 84 assertEq(env.qualified, false); 85 assertEq(env.unqualified, false); 86 assertEq(env.lexical, false); 87 assertEq(env.prop, false); 88 assertEq(env.bindings_prop, true, "bindings property must live in the with env for bindings"); 89 90 assertEq(env.bindings_prop_var, true, 91 "bindings property must live in the with env for bindings"); 92 assertEq(env.bindings_prop_var_value, 60, 93 "bindings property must be overwritten for var"); 94 assertEq(env.bindings_prop_lexical, true, 95 "bindings property must live in the with env for bindings"); 96 assertEq(env.bindings_prop_lexical_value, 71, 97 "bindings property must not be overwritten for lexical"); 98 assertEq(env.bindings_prop_unqualified, true, 99 "bindings property must live in the with env for bindings"); 100 assertEq(env.bindings_prop_unqualified_value, 80, 101 "bindings property must be overwritten for unqualified"); 102 103 env = envs[i]; i++; 104 assertEq(env.type, "[DebugProxy] CallObject"); 105 assertEq(env.qualified, true, "qualified var must live in the CallObject"); 106 assertEq(env.unqualified, false); 107 assertEq(env.lexical, false); 108 assertEq(env.prop, false); 109 assertEq(env.bindings_prop, false); 110 111 assertEq(env.bindings_prop_var, true, 112 "qualified var binding must be created in the CallObject even if it conflicts with the bindings object property"); 113 assertEq(env.bindings_prop_var_value, undefined, 114 "qualified var value must not be set if it conflicts with the bindings object property"); 115 assertEq(env.bindings_prop_lexical, false); 116 assertEq(env.bindings_prop_unqualified, false); 117 118 env = envs[i]; i++; 119 assertEq(env.type, "[DebugProxy] GlobalLexicalEnvironmentObject"); 120 assertEq(env.qualified, false); 121 assertEq(env.unqualified, false); 122 assertEq(env.lexical, false); 123 assertEq(env.prop, false); 124 assertEq(env.bindings_prop, false); 125 126 assertEq(env.bindings_prop_var, false); 127 assertEq(env.bindings_prop_lexical, false); 128 assertEq(env.bindings_prop_unqualified, false); 129 130 env = envs[i]; i++; 131 assertEq(env.type, "*global*"); 132 assertEq(env.qualified, false); 133 assertEq(env.unqualified, true, "unqualified name must live in the global"); 134 assertEq(env.lexical, false); 135 assertEq(env.prop, true, "this property must live in the global"); 136 assertEq(env.bindings_prop, false); 137 138 assertEq(env.bindings_prop_var, false); 139 assertEq(env.bindings_prop_lexical, false); 140 assertEq(env.bindings_prop_unqualified, false); 141 }; 142 143 g.eval(` 144 function target() { 145 } 146 target(); 147 `);