match-debugger.js (1815B)
1 // Debugger-oriented Pattern subclasses. 2 3 if (typeof Match !== 'function') { 4 load(libdir + 'match.js'); 5 } 6 7 class DebuggerObjectPattern extends Match.Pattern { 8 constructor(className, props) { 9 super(); 10 this.className = className; 11 if (props) { 12 this.props = Match.Pattern.OBJECT_WITH_EXACTLY(props); 13 } 14 } 15 16 match(actual) { 17 if (!(actual instanceof Debugger.Object)) { 18 throw new Match.MatchError(`Expected Debugger.Object, got ${actual}`); 19 } 20 21 if (actual.class !== this.className) { 22 throw new Match.MatchError(`Expected Debugger.Object of class ${this.className}, got Debugger.Object of class ${actual.class}`); 23 } 24 25 if (this.props !== undefined) { 26 const lifted = {}; 27 for (const name of actual.getOwnPropertyNames()) { 28 const desc = actual.getOwnPropertyDescriptor(name); 29 if (!('value' in desc)) { 30 throw new Match.MatchError(`Debugger.Object referent has non-value property ${JSON.stringify(name)}`); 31 } 32 lifted[name] = desc.value; 33 } 34 35 try { 36 this.props.match(lifted); 37 } catch (inner) { 38 if (!(inner instanceof Match.MatchError)) { 39 throw inner; 40 } 41 inner.message = `matching Debugger.Object referent properties:\n${inner.message}`; 42 throw inner; 43 } 44 } 45 46 return true; 47 } 48 } 49 50 // The Debugger API guarantees that various sorts of meta-objects are 1:1 with 51 // their referents, so it's often useful to check that two objects are === in 52 // patterns. 53 class DebuggerIdentical extends Match.Pattern { 54 constructor(expected) { 55 super(); 56 this.expected = expected; 57 } 58 59 match(actual) { 60 if (actual !== this.expected) { 61 throw new Pattern.MatchError(`Expected exact value ${uneval(this.expected)}, got ${uneval(actual)}`); 62 } 63 } 64 }