Skip to content

Commit

Permalink
Fix: Spinner getting stuck issue
Browse files Browse the repository at this point in the history
Fix #485
Close #494
  • Loading branch information
qzhou1607-zz authored and alrra committed Sep 7, 2017
1 parent 574b210 commit a5b9951
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 10 deletions.
47 changes: 47 additions & 0 deletions src/lib/connectors/jsdom/evaluate-runner.ts
@@ -0,0 +1,47 @@
import * as vm from 'vm';

import * as jsdom from 'jsdom/lib/old-api';
import * as jsdomutils from 'jsdom/lib/jsdom/living/generated/utils';

const run = (data) => {
const { source } = data;
const result = {
error: null,
evaluate: 'result'
};
const url = process.argv[2];
const waitFor = process.argv[3];

jsdom.env({
done: (error, window) => {
if (error) {
result.error = error;

return process.send(result);
}

/* Even though `done()` is called after window.onload (so all resoruces and scripts executed),
we might want to wait a few seconds if the site is lazy loading something. */
return setTimeout(async () => {
try {
const script: vm.Script = new vm.Script(source);
const evaluteResult = await script.runInContext(jsdomutils.implForWrapper(window.document)._global);

result.evaluate = evaluteResult;
} catch (err) {
result.error = err;
}

process.send(result);
}, waitFor);
},
features: {
FetchExternalResources: ['script', 'link', 'img'],
ProcessExternalResources: ['script'],
SkipExternalResources: false
},
url
});
};

process.on('message', run);
45 changes: 36 additions & 9 deletions src/lib/connectors/jsdom/jsdom.ts
Expand Up @@ -26,10 +26,9 @@
import * as path from 'path';
import * as url from 'url';
import * as util from 'util';
import * as vm from 'vm';
import { fork, ChildProcess } from 'child_process';

import * as jsdom from 'jsdom/lib/old-api';
import * as jsdomutils from 'jsdom/lib/jsdom/living/generated/utils';

import { debug as d } from '../../utils/debug';
import { resolveUrl } from '../utils/resolver';
Expand Down Expand Up @@ -464,15 +463,43 @@ class JSDOMConnector implements IConnector {
return this._fetchUrl(parsedTarget, customHeaders);
}

public evaluate(source: string): Promise<any> {
const script: vm.Script = new vm.Script(source);
const result = script.runInContext(jsdomutils.implForWrapper(this._window.document)._global, { timeout: 60000 });

if (result[Symbol.toStringTag] === 'Promise') {
return result;
private killProcess = (runner: ChildProcess) => {
try {
runner.kill('SIGKILL');
} catch (err) {
debug('Error closing evaluate process');
}
};

public evaluate(source: string, waitBeforeTimeOut: number = 60000): Promise<any> {
return new Promise((resolve, reject) => {
const runner: ChildProcess = fork(path.join(__dirname, 'evaluate-runner'), [this._finalHref, this._options.waitFor], { execArgv: [] });
let timeoutId;

runner.on('message', (result) => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}

this.killProcess(runner);

return Promise.resolve(result);
if (result.error) {
return reject(result.error);
}

return resolve(result.evaluate);
});

runner.send({ source });

timeoutId = setTimeout(() => {
debug(`Evaluation times out. Killing process and reporting and error.`);
this.killProcess(runner);

return reject(new Error('TIMEOUT'));
}, waitBeforeTimeOut);
});
}

public querySelectorAll(selector: string): Promise<Array<JSDOMAsyncHTMLElement>> {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/rules/axe/axe.ts
Expand Up @@ -11,7 +11,7 @@ import { AxeResults, Result as AxeResult, NodeResult as AxeNodeResult } from 'ax

import { readFileAsync } from '../../utils/misc';
import { debug as d } from '../../utils/debug';
import { IAsyncHTMLElement, ITraverseEnd, IRule, IRuleBuilder, Severity } from '../../types'; // eslint-disable-line no-unused-vars
import { IAsyncHTMLElement, IRule, IRuleBuilder, Severity, ITraverseEnd } from '../../types'; // eslint-disable-line no-unused-vars
import { RuleContext } from '../../rule-context'; // eslint-disable-line no-unused-vars

const debug = d(__filename);
Expand Down

0 comments on commit a5b9951

Please sign in to comment.