Source code

Revision control

Copy as Markdown

Other Tools

// Debugger-oriented Pattern subclasses.
if (typeof Match !== 'function') {
load(libdir + 'match.js');
}
class DebuggerObjectPattern extends Match.Pattern {
constructor(className, props) {
super();
this.className = className;
if (props) {
this.props = Match.Pattern.OBJECT_WITH_EXACTLY(props);
}
}
match(actual) {
if (!(actual instanceof Debugger.Object)) {
throw new Match.MatchError(`Expected Debugger.Object, got ${actual}`);
}
if (actual.class !== this.className) {
throw new Match.MatchError(`Expected Debugger.Object of class ${this.className}, got Debugger.Object of class ${actual.class}`);
}
if (this.props !== undefined) {
const lifted = {};
for (const name of actual.getOwnPropertyNames()) {
const desc = actual.getOwnPropertyDescriptor(name);
if (!('value' in desc)) {
throw new Match.MatchError(`Debugger.Object referent has non-value property ${JSON.stringify(name)}`);
}
lifted[name] = desc.value;
}
try {
this.props.match(lifted);
} catch (inner) {
if (!(inner instanceof Match.MatchError)) {
throw inner;
}
inner.message = `matching Debugger.Object referent properties:\n${inner.message}`;
throw inner;
}
}
return true;
}
}
// The Debugger API guarantees that various sorts of meta-objects are 1:1 with
// their referents, so it's often useful to check that two objects are === in
// patterns.
class DebuggerIdentical extends Match.Pattern {
constructor(expected) {
super();
this.expected = expected;
}
match(actual) {
if (actual !== this.expected) {
throw new Pattern.MatchError(`Expected exact value ${uneval(this.expected)}, got ${uneval(actual)}`);
}
}
}