Remove mutual recursion between Runner and TreeProcessor

This commit is contained in:
Steve Gravrock
2025-08-16 08:08:54 -07:00
parent d5884e33c6
commit ea3fc88803
4 changed files with 147 additions and 215 deletions

View File

@@ -9407,6 +9407,7 @@ getJasmineRequireObj().Runner = function(j$) {
#runableResources; #runableResources;
#runQueue; #runQueue;
#TreeProcessor; #TreeProcessor;
#treeProcessor;
#globalErrors; #globalErrors;
#reportDispatcher; #reportDispatcher;
#getConfig; #getConfig;
@@ -9469,12 +9470,9 @@ getJasmineRequireObj().Runner = function(j$) {
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
}); });
const processor = new this.#TreeProcessor({ this.#treeProcessor = new this.#TreeProcessor({
tree: this.#topSuite, tree: this.#topSuite,
runnableIds: runablesToRun, runnableIds: runablesToRun,
executeTopSuite: this.#executeTopSuite.bind(this),
executeSpec: this.#executeSpec.bind(this),
executeSuiteSegment: this.#executeSuiteSegment.bind(this),
orderChildren: function(node) { orderChildren: function(node) {
return order.sort(node.children); return order.sort(node.children);
}, },
@@ -9482,12 +9480,12 @@ getJasmineRequireObj().Runner = function(j$) {
return !config.specFilter(spec); return !config.specFilter(spec);
} }
}); });
processor.processTree(); this.#treeProcessor.processTree();
return this.#execute2(runablesToRun, order, processor); return this.#execute2(runablesToRun, order);
} }
async #execute2(runablesToRun, order, processor) { async #execute2(runablesToRun, order) {
const totalSpecsDefined = this.#getTotalSpecsDefined(); const totalSpecsDefined = this.#getTotalSpecsDefined();
this.#runableResources.initForRunable(this.#topSuite.id); this.#runableResources.initForRunable(this.#topSuite.id);
@@ -9511,7 +9509,7 @@ getJasmineRequireObj().Runner = function(j$) {
}); });
this.#currentlyExecutingSuites.push(this.#topSuite); this.#currentlyExecutingSuites.push(this.#topSuite);
await processor.execute(); await this.#executeTopSuite();
if (this.#topSuite.hadBeforeAllFailure) { if (this.#topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite); await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
@@ -9565,28 +9563,34 @@ getJasmineRequireObj().Runner = function(j$) {
return jasmineDoneInfo; return jasmineDoneInfo;
} }
// TreeProcessor callback. async #executeTopSuite() {
#executeTopSuite(topSuite, wrappedChildren, done) { const wrappedChildren = this.#wrapNodes(
this.#treeProcessor.childrenOfTopSuite()
);
const queueableFns = this.#addBeforeAndAfterAlls( const queueableFns = this.#addBeforeAndAfterAlls(
topSuite, this.#topSuite,
true,
wrappedChildren wrappedChildren
); );
this.#runQueueWithSkipPolicy({
queueableFns, await new Promise(resolve => {
userContext: topSuite.sharedUserContext(), this.#runQueueWithSkipPolicy({
onException: function() { queueableFns,
topSuite.handleException.apply(topSuite, arguments); userContext: this.#topSuite.sharedUserContext(),
}.bind(this), onException: function() {
onComplete: done, this.#topSuite.handleException.apply(this.#topSuite, arguments);
onMultipleDone: topSuite.onMultipleDone }.bind(this),
? topSuite.onMultipleDone.bind(topSuite) onComplete: resolve,
: null onMultipleDone: this.#topSuite.onMultipleDone
? this.#topSuite.onMultipleDone.bind(this.#topSuite)
: null
});
}); });
} }
// TreeProcessor callback. Mutually recursive with TreeProcessor##executeNode. #executeSuiteSegment(suite, segmentNumber, done) {
#executeSuiteSegment(suite, excluded, wrappedChildren, done) { const wrappedChildren = this.#wrapNodes(
this.#treeProcessor.childrenOfSuiteSegment(suite, segmentNumber)
);
const onStart = { const onStart = {
fn: next => { fn: next => {
this.#suiteSegmentStart(suite, next); this.#suiteSegmentStart(suite, next);
@@ -9594,7 +9598,7 @@ getJasmineRequireObj().Runner = function(j$) {
}; };
const queueableFns = [ const queueableFns = [
onStart, onStart,
...this.#addBeforeAndAfterAlls(suite, excluded, wrappedChildren) ...this.#addBeforeAndAfterAlls(suite, wrappedChildren)
]; ];
this.#runQueueWithSkipPolicy({ this.#runQueueWithSkipPolicy({
@@ -9617,27 +9621,40 @@ getJasmineRequireObj().Runner = function(j$) {
}); });
} }
// TreeProcessor callback. #executeSpec(spec, done) {
#executeSpec(spec, excluded, done) {
const config = this.#getConfig(); const config = this.#getConfig();
spec.execute( spec.execute(
this.#runQueueWithSkipPolicy.bind(this), this.#runQueueWithSkipPolicy.bind(this),
this.#globalErrors, this.#globalErrors,
done, done,
excluded, this.#treeProcessor.isExcluded(spec),
config.failSpecWithNoExpectations, config.failSpecWithNoExpectations,
config.detectLateRejectionHandling config.detectLateRejectionHandling
); );
} }
#addBeforeAndAfterAlls(suite, willExecute, wrappedChildren) { #wrapNodes(nodes) {
if (willExecute) { return nodes.map(node => {
return suite.beforeAllFns return {
.concat(wrappedChildren) fn: done => {
.concat(suite.afterAllFns); if (node.suite) {
} else { this.#executeSuiteSegment(node.suite, node.segmentNumber, done);
} else {
this.#executeSpec(node.spec, done);
}
}
};
});
}
#addBeforeAndAfterAlls(suite, wrappedChildren) {
if (this.#treeProcessor.isExcluded(suite)) {
return wrappedChildren; return wrappedChildren;
} }
return suite.beforeAllFns
.concat(wrappedChildren)
.concat(suite.afterAllFns);
} }
#suiteSegmentStart(suite, next) { #suiteSegmentStart(suite, next) {
@@ -11386,9 +11403,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
class TreeProcessor { class TreeProcessor {
#tree; #tree;
#executeTopSuite;
#executeSpec;
#executeSuiteSegment;
#runnableIds; #runnableIds;
#orderChildren; #orderChildren;
#excludeNode; #excludeNode;
@@ -11398,9 +11412,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
constructor(attrs) { constructor(attrs) {
this.#tree = attrs.tree; this.#tree = attrs.tree;
this.#runnableIds = attrs.runnableIds; this.#runnableIds = attrs.runnableIds;
this.#executeTopSuite = attrs.executeTopSuite;
this.#executeSpec = attrs.executeSpec;
this.#executeSuiteSegment = attrs.executeSuiteSegment;
this.#orderChildren = this.#orderChildren =
attrs.orderChildren || attrs.orderChildren ||
@@ -11412,7 +11423,7 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
function(node) { function(node) {
return false; return false;
}; };
this.#stats = { valid: true }; this.#stats = {};
this.#processed = false; this.#processed = false;
} }
@@ -11422,22 +11433,27 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
return this.#stats; return this.#stats;
} }
async execute() { childrenOfTopSuite() {
if (!this.#processed) { return this.childrenOfSuiteSegment(this.#tree, 0);
this.processTree(); }
}
if (!this.#stats.valid) { childrenOfSuiteSegment(suite, segmentNumber) {
throw new Error('invalid order'); const segmentChildren = this.#stats[suite.id].segments[segmentNumber]
} .nodes;
return segmentChildren.map(function(child) {
const wrappedChildren = this.#wrapChildren(this.#tree, 0); if (child.owner.children) {
return { suite: child.owner, segmentNumber: child.index };
await new Promise(resolve => { } else {
this.#executeTopSuite(this.#tree, wrappedChildren, resolve); return { spec: child.owner };
}
}); });
} }
isExcluded(node) {
const nodeStats = this.#stats[node.id];
return node.children ? !nodeStats.willExecute : nodeStats.excluded;
}
#runnableIndex(id) { #runnableIndex(id) {
for (let i = 0; i < this.#runnableIds.length; i++) { for (let i = 0; i < this.#runnableIds.length; i++) {
if (this.#runnableIds[i] === id) { if (this.#runnableIds[i] === id) {
@@ -11475,15 +11491,8 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
for (let i = 0; i < orderedChildren.length; i++) { for (let i = 0; i < orderedChildren.length; i++) {
const child = orderedChildren[i]; const child = orderedChildren[i];
this.#processNode(child, parentExcluded); this.#processNode(child, parentExcluded);
if (!this.#stats.valid) {
return;
}
const childStats = this.#stats[child.id]; const childStats = this.#stats[child.id];
hasExecutableChild = hasExecutableChild || childStats.willExecute; hasExecutableChild = hasExecutableChild || childStats.willExecute;
} }
@@ -11500,7 +11509,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.' 'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
); );
} else { } else {
this.#stats = { valid: false };
throw new Error( throw new Error(
'Invalid order: would cause a beforeAll or afterAll to be run multiple times' 'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
); );
@@ -11508,37 +11516,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
} }
} }
} }
#wrapChildren(node, segmentNumber) {
const result = [],
segmentChildren = this.#stats[node.id].segments[segmentNumber].nodes;
for (let i = 0; i < segmentChildren.length; i++) {
result.push(
this.#executeNode(segmentChildren[i].owner, segmentChildren[i].index)
);
}
return result;
}
#executeNode(node, segmentNumber) {
if (node.children) {
return {
fn: done => {
const wrappedChildren = this.#wrapChildren(node, segmentNumber);
const willExecute = this.#stats[node.id].willExecute;
this.#executeSuiteSegment(node, willExecute, wrappedChildren, done);
}
};
} else {
return {
fn: done => {
this.#executeSpec(node, this.#stats[node.id].excluded, done);
}
};
}
}
} }
function segmentChildren(node, orderedChildren, stats, executableIndex) { function segmentChildren(node, orderedChildren, stats, executableIndex) {

View File

@@ -34,8 +34,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({ expect(result[leaf.id]).toEqual({
excluded: false, excluded: false,
willExecute: true, willExecute: true,
@@ -51,8 +49,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({ expect(result[leaf.id]).toEqual({
excluded: false, excluded: false,
willExecute: false, willExecute: false,
@@ -68,8 +64,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({ expect(result[leaf.id]).toEqual({
excluded: true, excluded: true,
willExecute: false, willExecute: false,
@@ -88,8 +82,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({ expect(result[leaf.id]).toEqual({
excluded: true, excluded: true,
willExecute: false, willExecute: false,
@@ -106,8 +98,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[parent.id]).toEqual({ expect(result[parent.id]).toEqual({
excluded: false, excluded: false,
willExecute: true, willExecute: true,
@@ -130,8 +120,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[parent.id]).toEqual({ expect(result[parent.id]).toEqual({
excluded: false, excluded: false,
willExecute: false, willExecute: false,
@@ -166,8 +154,6 @@ describe('TreeProcessor', function() {
}), }),
result = processor.processTree(); result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[root.id]).toEqual({ expect(result[root.id]).toEqual({
excluded: false, excluded: false,
willExecute: true, willExecute: true,
@@ -217,7 +203,7 @@ describe('TreeProcessor', function() {
}); });
}); });
it('marks the run order invalid if it would re-enter a node that does not allow re-entry', async function() { it('throws if the specified order would re-enter a node that does not allow re-entry', function() {
const leaf1 = new Leaf(), const leaf1 = new Leaf(),
leaf2 = new Leaf(), leaf2 = new Leaf(),
leaf3 = new Leaf(), leaf3 = new Leaf(),
@@ -233,14 +219,9 @@ describe('TreeProcessor', function() {
}).toThrowError( }).toThrowError(
'Invalid order: would cause a beforeAll or afterAll to be run multiple times' 'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
); );
// Subsequent attempts to execute should fail
await expectAsync(processor.execute()).toBeRejectedWithError(
'invalid order'
);
}); });
it('marks the run order valid if a node being re-entered allows re-entry', function() { it('does not throw if a node being re-entered allows re-entry', function() {
const leaf1 = new Leaf(); const leaf1 = new Leaf();
const leaf2 = new Leaf(); const leaf2 = new Leaf();
const leaf3 = new Leaf(); const leaf3 = new Leaf();
@@ -253,15 +234,14 @@ describe('TreeProcessor', function() {
const env = jasmineUnderTest.getEnv(); const env = jasmineUnderTest.getEnv();
spyOn(env, 'deprecated'); spyOn(env, 'deprecated');
const result = processor.processTree(); processor.processTree();
expect(result.valid).toBe(true);
expect(env.deprecated).toHaveBeenCalledWith( expect(env.deprecated).toHaveBeenCalledWith(
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.' 'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
); );
}); });
it("marks the run order valid if a node which can't be re-entered is only entered once", function() { it("does not throw if a node which can't be re-entered is only entered once", function() {
const leaf1 = new Leaf(), const leaf1 = new Leaf(),
leaf2 = new Leaf(), leaf2 = new Leaf(),
leaf3 = new Leaf(), leaf3 = new Leaf(),
@@ -270,22 +250,20 @@ describe('TreeProcessor', function() {
processor = new jasmineUnderTest.TreeProcessor({ processor = new jasmineUnderTest.TreeProcessor({
tree: root, tree: root,
runnableIds: [leaf2.id, leaf1.id, leaf3.id] runnableIds: [leaf2.id, leaf1.id, leaf3.id]
}), });
result = processor.processTree();
expect(result.valid).toBe(true); processor.processTree();
}); });
it("marks the run order valid if a node which can't be re-entered is run directly", function() { it("does not throw if a node which can't be re-entered is run directly", function() {
const noReentry = new Node({ noReenter: true }), const noReentry = new Node({ noReenter: true }),
root = new Node({ children: [noReentry] }), root = new Node({ children: [noReentry] }),
processor = new jasmineUnderTest.TreeProcessor({ processor = new jasmineUnderTest.TreeProcessor({
tree: root, tree: root,
runnableIds: [root.id] runnableIds: [root.id]
}), });
result = processor.processTree();
expect(result.valid).toBe(true); processor.processTree();
}); });
// TODO: Replace these with corresponding unit tests elsewhere, once things stabilize // TODO: Replace these with corresponding unit tests elsewhere, once things stabilize

View File

@@ -6,6 +6,7 @@ getJasmineRequireObj().Runner = function(j$) {
#runableResources; #runableResources;
#runQueue; #runQueue;
#TreeProcessor; #TreeProcessor;
#treeProcessor;
#globalErrors; #globalErrors;
#reportDispatcher; #reportDispatcher;
#getConfig; #getConfig;
@@ -68,12 +69,9 @@ getJasmineRequireObj().Runner = function(j$) {
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
}); });
const processor = new this.#TreeProcessor({ this.#treeProcessor = new this.#TreeProcessor({
tree: this.#topSuite, tree: this.#topSuite,
runnableIds: runablesToRun, runnableIds: runablesToRun,
executeTopSuite: this.#executeTopSuite.bind(this),
executeSpec: this.#executeSpec.bind(this),
executeSuiteSegment: this.#executeSuiteSegment.bind(this),
orderChildren: function(node) { orderChildren: function(node) {
return order.sort(node.children); return order.sort(node.children);
}, },
@@ -81,12 +79,12 @@ getJasmineRequireObj().Runner = function(j$) {
return !config.specFilter(spec); return !config.specFilter(spec);
} }
}); });
processor.processTree(); this.#treeProcessor.processTree();
return this.#execute2(runablesToRun, order, processor); return this.#execute2(runablesToRun, order);
} }
async #execute2(runablesToRun, order, processor) { async #execute2(runablesToRun, order) {
const totalSpecsDefined = this.#getTotalSpecsDefined(); const totalSpecsDefined = this.#getTotalSpecsDefined();
this.#runableResources.initForRunable(this.#topSuite.id); this.#runableResources.initForRunable(this.#topSuite.id);
@@ -110,7 +108,7 @@ getJasmineRequireObj().Runner = function(j$) {
}); });
this.#currentlyExecutingSuites.push(this.#topSuite); this.#currentlyExecutingSuites.push(this.#topSuite);
await processor.execute(); await this.#executeTopSuite();
if (this.#topSuite.hadBeforeAllFailure) { if (this.#topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite); await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
@@ -164,28 +162,34 @@ getJasmineRequireObj().Runner = function(j$) {
return jasmineDoneInfo; return jasmineDoneInfo;
} }
// TreeProcessor callback. async #executeTopSuite() {
#executeTopSuite(topSuite, wrappedChildren, done) { const wrappedChildren = this.#wrapNodes(
this.#treeProcessor.childrenOfTopSuite()
);
const queueableFns = this.#addBeforeAndAfterAlls( const queueableFns = this.#addBeforeAndAfterAlls(
topSuite, this.#topSuite,
true,
wrappedChildren wrappedChildren
); );
this.#runQueueWithSkipPolicy({
queueableFns, await new Promise(resolve => {
userContext: topSuite.sharedUserContext(), this.#runQueueWithSkipPolicy({
onException: function() { queueableFns,
topSuite.handleException.apply(topSuite, arguments); userContext: this.#topSuite.sharedUserContext(),
}.bind(this), onException: function() {
onComplete: done, this.#topSuite.handleException.apply(this.#topSuite, arguments);
onMultipleDone: topSuite.onMultipleDone }.bind(this),
? topSuite.onMultipleDone.bind(topSuite) onComplete: resolve,
: null onMultipleDone: this.#topSuite.onMultipleDone
? this.#topSuite.onMultipleDone.bind(this.#topSuite)
: null
});
}); });
} }
// TreeProcessor callback. Mutually recursive with TreeProcessor##executeNode. #executeSuiteSegment(suite, segmentNumber, done) {
#executeSuiteSegment(suite, excluded, wrappedChildren, done) { const wrappedChildren = this.#wrapNodes(
this.#treeProcessor.childrenOfSuiteSegment(suite, segmentNumber)
);
const onStart = { const onStart = {
fn: next => { fn: next => {
this.#suiteSegmentStart(suite, next); this.#suiteSegmentStart(suite, next);
@@ -193,7 +197,7 @@ getJasmineRequireObj().Runner = function(j$) {
}; };
const queueableFns = [ const queueableFns = [
onStart, onStart,
...this.#addBeforeAndAfterAlls(suite, excluded, wrappedChildren) ...this.#addBeforeAndAfterAlls(suite, wrappedChildren)
]; ];
this.#runQueueWithSkipPolicy({ this.#runQueueWithSkipPolicy({
@@ -216,27 +220,40 @@ getJasmineRequireObj().Runner = function(j$) {
}); });
} }
// TreeProcessor callback. #executeSpec(spec, done) {
#executeSpec(spec, excluded, done) {
const config = this.#getConfig(); const config = this.#getConfig();
spec.execute( spec.execute(
this.#runQueueWithSkipPolicy.bind(this), this.#runQueueWithSkipPolicy.bind(this),
this.#globalErrors, this.#globalErrors,
done, done,
excluded, this.#treeProcessor.isExcluded(spec),
config.failSpecWithNoExpectations, config.failSpecWithNoExpectations,
config.detectLateRejectionHandling config.detectLateRejectionHandling
); );
} }
#addBeforeAndAfterAlls(suite, willExecute, wrappedChildren) { #wrapNodes(nodes) {
if (willExecute) { return nodes.map(node => {
return suite.beforeAllFns return {
.concat(wrappedChildren) fn: done => {
.concat(suite.afterAllFns); if (node.suite) {
} else { this.#executeSuiteSegment(node.suite, node.segmentNumber, done);
} else {
this.#executeSpec(node.spec, done);
}
}
};
});
}
#addBeforeAndAfterAlls(suite, wrappedChildren) {
if (this.#treeProcessor.isExcluded(suite)) {
return wrappedChildren; return wrappedChildren;
} }
return suite.beforeAllFns
.concat(wrappedChildren)
.concat(suite.afterAllFns);
} }
#suiteSegmentStart(suite, next) { #suiteSegmentStart(suite, next) {

View File

@@ -4,9 +4,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
class TreeProcessor { class TreeProcessor {
#tree; #tree;
#executeTopSuite;
#executeSpec;
#executeSuiteSegment;
#runnableIds; #runnableIds;
#orderChildren; #orderChildren;
#excludeNode; #excludeNode;
@@ -16,9 +13,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
constructor(attrs) { constructor(attrs) {
this.#tree = attrs.tree; this.#tree = attrs.tree;
this.#runnableIds = attrs.runnableIds; this.#runnableIds = attrs.runnableIds;
this.#executeTopSuite = attrs.executeTopSuite;
this.#executeSpec = attrs.executeSpec;
this.#executeSuiteSegment = attrs.executeSuiteSegment;
this.#orderChildren = this.#orderChildren =
attrs.orderChildren || attrs.orderChildren ||
@@ -30,7 +24,7 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
function(node) { function(node) {
return false; return false;
}; };
this.#stats = { valid: true }; this.#stats = {};
this.#processed = false; this.#processed = false;
} }
@@ -40,22 +34,27 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
return this.#stats; return this.#stats;
} }
async execute() { childrenOfTopSuite() {
if (!this.#processed) { return this.childrenOfSuiteSegment(this.#tree, 0);
this.processTree(); }
}
if (!this.#stats.valid) { childrenOfSuiteSegment(suite, segmentNumber) {
throw new Error('invalid order'); const segmentChildren = this.#stats[suite.id].segments[segmentNumber]
} .nodes;
return segmentChildren.map(function(child) {
const wrappedChildren = this.#wrapChildren(this.#tree, 0); if (child.owner.children) {
return { suite: child.owner, segmentNumber: child.index };
await new Promise(resolve => { } else {
this.#executeTopSuite(this.#tree, wrappedChildren, resolve); return { spec: child.owner };
}
}); });
} }
isExcluded(node) {
const nodeStats = this.#stats[node.id];
return node.children ? !nodeStats.willExecute : nodeStats.excluded;
}
#runnableIndex(id) { #runnableIndex(id) {
for (let i = 0; i < this.#runnableIds.length; i++) { for (let i = 0; i < this.#runnableIds.length; i++) {
if (this.#runnableIds[i] === id) { if (this.#runnableIds[i] === id) {
@@ -93,15 +92,8 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
for (let i = 0; i < orderedChildren.length; i++) { for (let i = 0; i < orderedChildren.length; i++) {
const child = orderedChildren[i]; const child = orderedChildren[i];
this.#processNode(child, parentExcluded); this.#processNode(child, parentExcluded);
if (!this.#stats.valid) {
return;
}
const childStats = this.#stats[child.id]; const childStats = this.#stats[child.id];
hasExecutableChild = hasExecutableChild || childStats.willExecute; hasExecutableChild = hasExecutableChild || childStats.willExecute;
} }
@@ -118,7 +110,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.' 'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
); );
} else { } else {
this.#stats = { valid: false };
throw new Error( throw new Error(
'Invalid order: would cause a beforeAll or afterAll to be run multiple times' 'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
); );
@@ -126,37 +117,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
} }
} }
} }
#wrapChildren(node, segmentNumber) {
const result = [],
segmentChildren = this.#stats[node.id].segments[segmentNumber].nodes;
for (let i = 0; i < segmentChildren.length; i++) {
result.push(
this.#executeNode(segmentChildren[i].owner, segmentChildren[i].index)
);
}
return result;
}
#executeNode(node, segmentNumber) {
if (node.children) {
return {
fn: done => {
const wrappedChildren = this.#wrapChildren(node, segmentNumber);
const willExecute = this.#stats[node.id].willExecute;
this.#executeSuiteSegment(node, willExecute, wrappedChildren, done);
}
};
} else {
return {
fn: done => {
this.#executeSpec(node, this.#stats[node.id].excluded, done);
}
};
}
}
} }
function segmentChildren(node, orderedChildren, stats, executableIndex) { function segmentChildren(node, orderedChildren, stats, executableIndex) {