LibJS: Treat class definition parts as strict
Record the generator's strictness for each emitted bytecode instruction, instead of applying the executable's final strictness to every instruction during assembly. This lets class heritage and computed element names run with strict assignment semantics inside sloppy scripts. Also create the class self-binding as a strict immutable binding, matching ClassDefinitionEvaluation, and cover strict class heritage and computed names in the runtime tests.
This commit is contained in:
parent
6d36517042
commit
4046f65ae7
24 changed files with 89 additions and 44 deletions
|
|
@ -22,7 +22,7 @@ pub struct SourceMapEntry {
|
|||
/// serialized into the final byte stream.
|
||||
pub struct BasicBlock {
|
||||
pub index: u32,
|
||||
pub instructions: Vec<(Instruction, SourceMapEntry)>,
|
||||
pub instructions: Vec<(Instruction, SourceMapEntry, bool)>,
|
||||
pub handler: Option<Label>,
|
||||
pub terminated: bool,
|
||||
pub resolved_this: bool,
|
||||
|
|
@ -39,9 +39,9 @@ impl BasicBlock {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn append(&mut self, instruction: Instruction, source_map: SourceMapEntry) {
|
||||
pub fn append(&mut self, instruction: Instruction, source_map: SourceMapEntry, strict: bool) {
|
||||
let is_terminator = instruction.is_terminator();
|
||||
self.instructions.push((instruction, source_map));
|
||||
self.instructions.push((instruction, source_map, strict));
|
||||
if is_terminator {
|
||||
self.terminated = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,20 @@ pub fn generate_expression(
|
|||
result
|
||||
}
|
||||
|
||||
fn generate_class_part_expression(
|
||||
expression: &Expression,
|
||||
generator: &mut Generator,
|
||||
preferred_dst: Option<&ScopedOperand>,
|
||||
) -> Option<ScopedOperand> {
|
||||
// https://tc39.es/ecma262/#sec-strict-mode-code
|
||||
// All parts of a |ClassDeclaration| or a |ClassExpression| are strict mode code.
|
||||
let saved_strict = generator.strict;
|
||||
generator.strict = true;
|
||||
let result = generate_expression(expression, generator, preferred_dst);
|
||||
generator.strict = saved_strict;
|
||||
result
|
||||
}
|
||||
|
||||
fn emit_get_binding(
|
||||
generator: &mut Generator,
|
||||
dst: Operand,
|
||||
|
|
@ -5750,7 +5764,9 @@ fn generate_class_expression(
|
|||
});
|
||||
generator.push_static_lexical_environment(class_env.clone());
|
||||
|
||||
// Step 3.a: Create binding for the class name in the class environment.
|
||||
// https://tc39.es/ecma262/#sec-runtime-semantics-classdefinitionevaluation
|
||||
// If _classBinding_ is not *undefined*, then
|
||||
// Perform ! _classEnv_.CreateImmutableBinding(_classBinding_, *true*).
|
||||
// Only emit when the class has a name, or when there's no lhs_name
|
||||
// (skip this for anonymous classes with lhs_name).
|
||||
if data.name.is_some() || lhs_name.is_none() {
|
||||
|
|
@ -5765,13 +5781,13 @@ fn generate_class_expression(
|
|||
mode: EnvironmentMode::Lexical as u32,
|
||||
is_immutable: true,
|
||||
is_global: false,
|
||||
is_strict: false,
|
||||
is_strict: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Evaluate super class if present
|
||||
let super_class = if let Some(super_expression) = &data.super_class {
|
||||
generate_expression(super_expression, generator, None)
|
||||
generate_class_part_expression(super_expression, generator, None)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -5807,7 +5823,7 @@ fn generate_class_expression(
|
|||
match &element_node.inner {
|
||||
ClassElement::Method { key, .. } => {
|
||||
if !is_private_key(key) {
|
||||
let key_val = generate_expression(key, generator, None);
|
||||
let key_val = generate_class_part_expression(key, generator, None);
|
||||
element_keys.push(key_val);
|
||||
} else {
|
||||
element_keys.push(None);
|
||||
|
|
@ -5815,7 +5831,7 @@ fn generate_class_expression(
|
|||
}
|
||||
ClassElement::Field { key, .. } => {
|
||||
if !is_private_key(key) {
|
||||
let key_val = generate_expression(key, generator, None);
|
||||
let key_val = generate_class_part_expression(key, generator, None);
|
||||
element_keys.push(key_val);
|
||||
} else {
|
||||
element_keys.push(None);
|
||||
|
|
|
|||
|
|
@ -847,7 +847,7 @@ impl Generator {
|
|||
column: self.current_source_start.column,
|
||||
};
|
||||
let block = &mut self.basic_blocks[self.current_block_index.basic_block_index()];
|
||||
block.append(instruction, source_map);
|
||||
block.append(instruction, source_map, self.strict);
|
||||
}
|
||||
|
||||
/// Emit a Mov instruction (optimized away if src == dst).
|
||||
|
|
@ -882,7 +882,7 @@ impl Generator {
|
|||
// instruction is a comparison whose dst matches condition, fuse into a JumpXxx.
|
||||
if condition.operand().is_register() && std::rc::Rc::strong_count(&condition.inner) == 1 {
|
||||
let block = &mut self.basic_blocks[self.current_block_index.basic_block_index()];
|
||||
if let Some((last_instruction, _)) = block.instructions.last() {
|
||||
if let Some((last_instruction, _, _)) = block.instructions.last() {
|
||||
let fused = match last_instruction {
|
||||
Instruction::LessThan { dst, lhs, rhs } if *dst == condition.operand() => {
|
||||
Some(Instruction::JumpLessThan {
|
||||
|
|
@ -1563,6 +1563,7 @@ impl Generator {
|
|||
Instruction::GetLexicalEnvironment {
|
||||
dst,
|
||||
},
|
||||
_,
|
||||
_
|
||||
)) if *dst == saved_environment
|
||||
)
|
||||
|
|
@ -1574,7 +1575,7 @@ impl Generator {
|
|||
.instructions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.any(|(instruction_index, (instruction, _))| {
|
||||
.any(|(instruction_index, (instruction, _, _))| {
|
||||
if block_index == load_block_index && instruction_index == 0 {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1612,7 +1613,7 @@ impl Generator {
|
|||
// Phase 1: Operand rewriting
|
||||
let mut max_argument_index: Option<u32> = None;
|
||||
for block in &mut self.basic_blocks {
|
||||
for (instruction, _) in &mut block.instructions {
|
||||
for (instruction, _, _) in &mut block.instructions {
|
||||
instruction.visit_operands(&mut |op: &mut Operand| {
|
||||
match op.operand_type() {
|
||||
OperandType::Register => {} // stays as-is
|
||||
|
|
@ -1733,7 +1734,7 @@ impl Generator {
|
|||
block_offsets.push(offset);
|
||||
let block = &self.basic_blocks[block_index];
|
||||
let mut block_actions = Vec::with_capacity(block.instructions.len());
|
||||
for (instruction, _) in &block.instructions {
|
||||
for (instruction, _, _) in &block.instructions {
|
||||
match instruction {
|
||||
Instruction::Jump { target } => {
|
||||
let target_block = target.0 as usize;
|
||||
|
|
@ -1824,7 +1825,7 @@ impl Generator {
|
|||
|
||||
// Phase 3: Patch labels (block index → byte offset)
|
||||
for block in &mut self.basic_blocks {
|
||||
for (instruction, _) in &mut block.instructions {
|
||||
for (instruction, _, _) in &mut block.instructions {
|
||||
instruction.visit_labels(&mut |label: &mut Label| {
|
||||
let block_index = label.0 as usize;
|
||||
label.0 = u32_from_usize(block_offsets[block_index]);
|
||||
|
|
@ -1854,7 +1855,7 @@ impl Generator {
|
|||
let handler = block.handler;
|
||||
let block_actions = &actions[block_index];
|
||||
|
||||
for (instruction_index, (instruction, sm)) in block.instructions.iter().enumerate() {
|
||||
for (instruction_index, (instruction, sm, strict)) in block.instructions.iter().enumerate() {
|
||||
let action = block_actions[instruction_index];
|
||||
match action {
|
||||
InstAction::Skip => {
|
||||
|
|
@ -1874,7 +1875,7 @@ impl Generator {
|
|||
column: sm.column,
|
||||
},
|
||||
);
|
||||
instruction.encode(self.strict, &mut bytecode);
|
||||
instruction.encode(*strict, &mut bytecode);
|
||||
}
|
||||
InstAction::JumpToReturn(value) => {
|
||||
let instruction_offset = bytecode.len();
|
||||
|
|
@ -1887,7 +1888,7 @@ impl Generator {
|
|||
},
|
||||
);
|
||||
let replacement = Instruction::Return { value };
|
||||
replacement.encode(self.strict, &mut bytecode);
|
||||
replacement.encode(*strict, &mut bytecode);
|
||||
}
|
||||
InstAction::JumpToEnd(value) => {
|
||||
let instruction_offset = bytecode.len();
|
||||
|
|
@ -1900,7 +1901,7 @@ impl Generator {
|
|||
},
|
||||
);
|
||||
let replacement = Instruction::End { value };
|
||||
replacement.encode(self.strict, &mut bytecode);
|
||||
replacement.encode(*strict, &mut bytecode);
|
||||
}
|
||||
InstAction::EmitJumpFalse { condition, mut target } => {
|
||||
// Patch label for the target
|
||||
|
|
@ -1916,7 +1917,7 @@ impl Generator {
|
|||
},
|
||||
);
|
||||
let replacement = Instruction::JumpFalse { condition, target };
|
||||
replacement.encode(self.strict, &mut bytecode);
|
||||
replacement.encode(*strict, &mut bytecode);
|
||||
}
|
||||
InstAction::EmitJumpTrue { condition, mut target } => {
|
||||
let target_block = target.0 as usize;
|
||||
|
|
@ -1931,7 +1932,7 @@ impl Generator {
|
|||
},
|
||||
);
|
||||
let replacement = Instruction::JumpTrue { condition, target };
|
||||
replacement.encode(self.strict, &mut bytecode);
|
||||
replacement.encode(*strict, &mut bytecode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ f$0a149d9a class-computed-key.js:4:5
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable ``, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable ``, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] GetGlobal dst:reg6, `Symbol`
|
||||
[ 40] GetById dst:reg7, base:reg6, `iterator` (Symbol.iterator)
|
||||
[ 58] SetLexicalEnvironment environment:reg4
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ classWithName$155d62f1 class-environment.js:2:13
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `Foo`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `Foo`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:C~0, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("method")]
|
||||
[ 60] CallConstruct dst:reg6, callee:C~0, C
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ test$fa7458d4 class-literal-fields.js:2:5
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("x"), element_keys:String("y"), element_keys:String("z"), element_keys:String("w"), element_keys:String("s"), element_keys:String("computed")]
|
||||
[ 70] Mov dst:A~0, src:reg6
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ $6a8031db delete-super-eval-order.js:4:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("m")]
|
||||
[ 60] DynamicInitializeLexicalBinding `A`, src:reg6
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ $6fa5e397 delete-super-property.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("foo"), element_keys:String("baz")]
|
||||
[ 60] DynamicInitializeLexicalBinding `A`, src:reg6
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ block6:
|
|||
|
||||
block7:
|
||||
[ f0] CreateLexicalEnvironment dst:reg13, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 108] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 108] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 118] SetLexicalEnvironment environment:reg4
|
||||
[ 120] NewClass dst:reg14, class_environment:reg13, class_blueprint_index:0
|
||||
[ 140] Mov dst:reg12, src:reg14
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ block6:
|
|||
|
||||
block7:
|
||||
[ d8] CreateLexicalEnvironment dst:reg13, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ f0] CreateVariable `Foo`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ f0] CreateVariable `Foo`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 100] SetLexicalEnvironment environment:reg4
|
||||
[ 108] NewClass dst:reg14, class_environment:reg13, class_blueprint_index:0
|
||||
[ 128] Mov dst:reg12, src:reg14
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ $745d24d5 numeric-class-field-name.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:Int32(42)]
|
||||
[ 60] DynamicInitializeLexicalBinding `C`, src:reg6
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ $79e506f5 postfix-increment-private-member.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] CreatePrivateEnvironment
|
||||
[ 38] AddPrivateName `#c`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ $7f6ce915 private-identifier-access-patterns.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] CreatePrivateEnvironment
|
||||
[ 38] AddPrivateName `#x`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ $79e506f5 private-logical-assignment-register-order.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] CreatePrivateEnvironment
|
||||
[ 38] AddPrivateName `#x`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ $79e506f5 private-method-call-description.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] CreatePrivateEnvironment
|
||||
[ 38] AddPrivateName `#m`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ $091ab4cd super-call-spread-register-order.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] GetGlobal dst:reg6, `Object`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
[ 48] NewClass dst:reg7, super_class:reg6, class_environment:reg5, class_blueprint_index:0
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ $a37cd2a2 super-computed-eval-order.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `Base`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `Base`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0
|
||||
[ 58] DynamicInitializeLexicalBinding `Base`, src:reg6
|
||||
[ 68] CreateLexicalEnvironment dst:reg6, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 80] CreateVariable `Derived`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 80] CreateVariable `Derived`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 90] GetGlobal dst:reg5, `Base`
|
||||
[ a0] SetLexicalEnvironment environment:reg4
|
||||
[ a8] NewClass dst:reg7, super_class:reg5, class_environment:reg6, class_blueprint_index:1, element_keys:[element_keys:String("test")]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ $091ab4cd super-computed-string-to-id.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] GetGlobal dst:reg6, `Object`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
[ 48] NewClass dst:reg7, super_class:reg6, class_environment:reg5, class_blueprint_index:0
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ $2a66ad4a super-constructor-call.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `Base`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `Base`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0
|
||||
[ 58] DynamicInitializeLexicalBinding `Base`, src:reg6
|
||||
[ 68] CreateLexicalEnvironment dst:reg6, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 80] CreateVariable `Derived`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 80] CreateVariable `Derived`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 90] GetGlobal dst:reg5, `Base`
|
||||
[ a0] SetLexicalEnvironment environment:reg4
|
||||
[ a8] NewClass dst:reg7, super_class:reg5, class_environment:reg6, class_blueprint_index:1
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ $460e17ea super-evaluation-order.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] GetGlobal dst:reg6, `Object`
|
||||
[ 40] SetLexicalEnvironment environment:reg4
|
||||
[ 48] NewClass dst:reg7, super_class:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("read"), element_keys:String("write"), element_keys:String("update")]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ $00cee19d super-for-of-resolve-order.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `C`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0
|
||||
[ 58] DynamicInitializeLexicalBinding `C`, src:reg6
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ $dc8f51ec super-length-access.js:3:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `A`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("length")]
|
||||
[ 60] DynamicInitializeLexicalBinding `A`, src:reg6
|
||||
[ 70] CreateLexicalEnvironment dst:reg6, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 88] CreateVariable `B`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 88] CreateVariable `B`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 98] GetGlobal dst:reg5, `A`
|
||||
[ a8] SetLexicalEnvironment environment:reg4
|
||||
[ b0] NewClass dst:reg7, super_class:reg5, class_environment:reg6, class_blueprint_index:1, element_keys:[element_keys:String("m")]
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ $1f56e90a super-optional-call-this.js:1:1
|
|||
block0:
|
||||
[ 0] GetLexicalEnvironment dst:reg4
|
||||
[ 8] CreateLexicalEnvironment dst:reg5, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 20] CreateVariable `Base`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 20] CreateVariable `Base`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 30] SetLexicalEnvironment environment:reg4
|
||||
[ 38] NewClass dst:reg6, class_environment:reg5, class_blueprint_index:0, element_keys:[element_keys:String("method")]
|
||||
[ 60] DynamicInitializeLexicalBinding `Base`, src:reg6
|
||||
[ 70] CreateLexicalEnvironment dst:reg6, parent:reg4, capacity:0, is_catch_environment:false
|
||||
[ 88] CreateVariable `Foo`, is_immutable:true, is_global:false, is_strict:false
|
||||
[ 88] CreateVariable `Foo`, is_immutable:true, is_global:false, is_strict:true
|
||||
[ 98] GetGlobal dst:reg5, `Base`
|
||||
[ a8] SetLexicalEnvironment environment:reg4
|
||||
[ b0] NewClass dst:reg7, super_class:reg5, class_environment:reg6, class_blueprint_index:1, element_keys:[element_keys:String("method")]
|
||||
|
|
|
|||
|
|
@ -19,3 +19,31 @@ test("class constructor prototype property descriptor", () => {
|
|||
expect(constructorDescriptor.enumerable).toBeFalse();
|
||||
expect(constructorDescriptor.configurable).toBeTrue();
|
||||
});
|
||||
|
||||
test("class heritage and computed property names are strict mode code", () => {
|
||||
expect(() => {
|
||||
class A {
|
||||
[(Object.preventExtensions({}).prop = 1)]() {}
|
||||
}
|
||||
}).toThrow(TypeError);
|
||||
|
||||
expect(() => {
|
||||
const A = class {
|
||||
[(Object.preventExtensions({}).prop = 1)]() {}
|
||||
};
|
||||
}).toThrow(TypeError);
|
||||
|
||||
expect(() => {
|
||||
class A {
|
||||
[(Object.preventExtensions({}).prop = 1)];
|
||||
}
|
||||
}).toThrow(TypeError);
|
||||
|
||||
expect(() => {
|
||||
class A extends (Object.preventExtensions({}).prop = 1) {}
|
||||
}).toThrow(TypeError);
|
||||
|
||||
expect(() => {
|
||||
const A = class extends (Object.preventExtensions({}).prop = 1) {};
|
||||
}).toThrow(TypeError);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue