GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — test_runner: cleanup test timeout abort listener by rluvaton · Pull Request #48915 · nodejs/node

Conversation

@rluvaton

@rluvaton rluvaton commented Jul 25, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

fix #48475

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bricss reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@nodejs-github-bot

nodejs-github-bot commented Jul 25, 2023

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/test_runner
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Jul 25, 2023
@rluvaton
rluvaton marked this pull request as ready for review July 25, 2023 09:44
rluvaton
rluvaton commented Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

rluvaton
rluvaton commented Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Outdated
Comment on lines 104 to 115

@rluvaton rluvaton Jul 25, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to put this in the setTimeout but for some reason, the test-runner-output.mjs test failed for the describe_it file with some missing stack trace

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
MoLow
MoLow reviewed Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

rluvaton
rluvaton commented Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Outdated
Comment on lines 92 to 108

@rluvaton rluvaton Jul 25, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done this to match the current behavior:

node/lib/timers/promises.js

Line 48 in 78f6952

reject(new AbortError(undefined, { cause: signal?.reason }));

but we should align it with just using an abort signal with no timeout - no error being thrown or throw an abort error

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
MoLow
MoLow reviewed Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

MoLow
MoLow reviewed Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

atlowChemi
atlowChemi reviewed Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Outdated
Comment on lines 87 to 93

@atlowChemi atlowChemi Jul 25, 2023

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could/Should this be an AbortSignal.any([signal, AbortSignal.timeout(timeout)]) etc?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rluvaton rluvaton Jul 25, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it would change anything as the timer won't get cleaned...

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@atlowChemi atlowChemi Jul 25, 2023

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean about the timer not getting clean?
The AbortSignal.any uses weak refs, so once this is GCed it would clear the timeout...

I think this suggestion could potentially reduce the complexity here, and also make it easier to land on v18, which doesn't have dispose & addAbortListener at the moment

WDYT?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rluvaton rluvaton Jul 25, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you! this is a much cleaner solution! the only problem here is that we create 2 new AbortSignal (AbortSignal.any and AbortSignal.timeout) for every describe/test/hook run, which can be bad for performance...

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rluvaton rluvaton Jul 25, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MoLow what do you think? should we remove the addAbortListener and dispose in order to support v18 and v16?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rluvaton rluvaton Jul 25, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this actually simplifies 😬

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@atlowChemi atlowChemi Jul 26, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rluvaton I had something like this in mind:

function stopTest(timeout, signal) {
  const timeoutSignal = timeout !== kDefaultTimeout && AbortSignal.timeout(timeout);
  const composedSignal = AbortSignal.any([signal, timeoutSignal].filter(Boolean));
  return PromisePrototypeThen(once(composedSignal, 'abort'), (e) => {
    if (e.target.reason !== timeoutSignal.reason) {
      return;
    }
    throw new ERR_TEST_FAILURE(
      `test timed out after ${timeout}ms`,
      kTestTimeoutFailure,
    );
  })
};

But current solution works for me 🙂

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rluvaton rluvaton Jul 26, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we accept the extra creation of an abort signal I highly prefer that

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@atlowChemi atlowChemi Jul 26, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we would want to profile both and decide based on that?
@MoLow @benjamingr what is your opinion here?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rluvaton rluvaton Jul 26, 2023

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created a benchmark PR and after it is merged we can check different solutions:

  • benchmark: add benchmarks for the test_runner #48931

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

atlowChemi reacted with heart emoji
All reactions
  • ❤️ 1 reaction
atlowChemi
atlowChemi reviewed Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread lib/internal/test_runner/test.js Outdated
Comment on lines 87 to 93

@atlowChemi atlowChemi Jul 25, 2023

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean about the timer not getting clean?
The AbortSignal.any uses weak refs, so once this is GCed it would clear the timeout...

I think this suggestion could potentially reduce the complexity here, and also make it easier to land on v18, which doesn't have dispose & addAbortListener at the moment

WDYT?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
ljharb
ljharb reviewed Jul 25, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@MoLow

MoLow commented Jul 25, 2023

Copy link
Copy Markdown
Member

@rluvaton see this implementation, I think a little cleaner and performant - WDYT? fa48543

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rluvaton

rluvaton commented Jul 25, 2023

Copy link
Copy Markdown
Member Author

@MoLow updated with your changes and modified to use ObjectDefineProperty

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

MoLow
MoLow approved these changes Jul 25, 2023
View reviewed changes
@MoLow
MoLow requested a review from benjamingr July 25, 2023 18:56
atlowChemi
atlowChemi reviewed Jul 26, 2023
View reviewed changes
Comment thread lib/internal/test_runner/test.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr requested changes Jul 26, 2023
View reviewed changes

@benjamingr benjamingr left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the promise+disposer in one object code pattern here + I don't like the explicit promise construction here.

We're core, we can "cheat", we can add the listener with [kWeakHandler]: test and it will cleanup the listener when the test is done.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@rluvaton

rluvaton commented Jul 26, 2023

Copy link
Copy Markdown
Member Author

We're core, we can "cheat", we can add the listener with [kWeakHandler]: test and it will cleanup the listener when the test is done.

to which listener? the abort listener? because using the aborted function from internal/abort_controller and passing the test as the resource did not work to clean up the abort listener

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@benjamingr

benjamingr commented Jul 26, 2023

Copy link
Copy Markdown
Member

The issue is the listener won't be removed right? kWeakListener means "remove the listener when that resource is gcd"

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rluvaton

rluvaton commented Jul 26, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

(I removed the timeout support so I try to make it work for the simple case)

I understand, but when I tried changing the stopTest function to using aborted (which under the hood use the kWeakHandler):

const { aborted } = require('internal/abort_controller');

function stopTest(timeout, signal) {
  return aborted(signal, {});
}

The test I wrote:

const { beforeEach, afterEach, test} = require("node:test");
beforeEach(() => {
  global.gc();
});
afterEach(() => {
  global.gc();
});

for (let i = 1; i <= 11; ++i) {
  test(`${i}`, () => {
  global.gc();
  });
}

it still log that:

(node:60047) MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 abort listeners added to [AbortSignal]. Use events.setMaxListeners() to increase limit
    at [kNewListener] (node:internal/event_target:542:17)
    at [kNewListener] (node:internal/abort_controller:239:24)
    at EventTarget.addEventListener (node:internal/event_target:655:23)
    at node:internal/test_runner/test:85:12
    at new Promise (<anonymous>)
    at stopTest (node:internal/test_runner/test:84:10)
    at TestHook.run (node:internal/test_runner/test:563:21)
    at TestHook.run (node:internal/test_runner/test:772:18)
    at node:internal/test_runner/test:519:20
    at async Test.runHook (node:internal/test_runner/test:517:7)

also when doing this it had the same effect:

function stopTest(timeout, signal) {
  return new Promise((resolve) => {
    signal.addEventListener('abort', resolve, { [kWeakHandler]: {} });
    setImmediate(() => {
      global.gc()
    }).unref()
  });
}

Maybe I'm missing something?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@atlowChemi

atlowChemi commented Jul 26, 2023

Copy link
Copy Markdown
Member

Maybe I'm missing something?

@rluvaton if we want to keep using the original signal we could keep updating kMaxEventTargetListeners, and since this AFAIK this signal is created internally we can probably safely assume we know how many listeners are being added...

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rluvaton

rluvaton commented Jul 26, 2023

Copy link
Copy Markdown
Member Author

The problem is that we are not cleaning up the abort listener (see that it still happening even when we GC manually)

atlowChemi reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rluvaton rluvaton mentioned this pull request Jul 26, 2023
benchmark: add benchmarks for the test_runner #48931
Merged
@rluvaton

rluvaton commented Jul 28, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

The reason why the warning still printed was because of #48951

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

benjamingr
benjamingr approved these changes Jul 29, 2023
View reviewed changes
rluvaton added 3 commits July 29, 2023 20:31
@rluvaton
test_runner: cleanup test timeout abort listener
272ff66
fix nodejs#48475
@rluvaton
added test
8657bc3
@rluvaton
fix with custom timeout as well
f19a8c2
@RafaelGSS

RafaelGSS commented Aug 17, 2023

Copy link
Copy Markdown
Member

Due to fact, #48877 didn't land cleanly on v20.x-staging. This PR somehow, depends on it. So we'll need a manual backport.

Reference: https://github.com/nodejs/node/blob/main/doc/contributing/backporting-to-release-lines.md

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@RafaelGSS RafaelGSS added the backport-requested-v20.x label Aug 17, 2023
@rluvaton rluvaton mentioned this pull request Aug 18, 2023
[v20.x backport] backport multiple test runner related prs #49225
Closed
@rluvaton

rluvaton commented Aug 18, 2023

Copy link
Copy Markdown
Member Author

Backport PR:

  • [v20.x backport] backport multiple test runner related prs #49225
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rluvaton rluvaton added backport-open-v20.x and removed backport-requested-v20.x labels Aug 18, 2023
rluvaton added a commit to rluvaton/node that referenced this pull request Sep 4, 2023
@rluvaton
test_runner: cleanup test timeout abort listener
b91c906
fix nodejs#48475

PR-URL: nodejs#48915
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
rluvaton added a commit to rluvaton/node that referenced this pull request Sep 4, 2023
@rluvaton
test: remove --no-warnings flag in test_runner fixtures
dbc3124
no longer needed after nodejs#48915 fix

PR-URL: nodejs#48989
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
UlisesGascon pushed a commit that referenced this pull request Sep 10, 2023
@rluvaton @UlisesGascon
test_runner: cleanup test timeout abort listener
c2f1830
fix #48475

PR-URL: #48915
Backport-PR-URL: #49225
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
UlisesGascon pushed a commit that referenced this pull request Sep 10, 2023
@rluvaton @UlisesGascon
test: remove --no-warnings flag in test_runner fixtures
4d184b5
no longer needed after #48915 fix

PR-URL: #48989
Backport-PR-URL: #49225
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
@UlisesGascon UlisesGascon mentioned this pull request Sep 10, 2023
v20.7.0 proposal #49592
Merged
cjihrig added a commit to cjihrig/node that referenced this pull request Sep 28, 2023
@cjihrig
test_runner: replace spurious if with else
1bb2d08
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: nodejs#48915
@cjihrig cjihrig mentioned this pull request Sep 28, 2023
test_runner: replace spurious if with else #49943
Merged
nodejs-github-bot pushed a commit that referenced this pull request Sep 29, 2023
@cjihrig
test_runner: replace spurious if with else
c935d4c
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: #48915
PR-URL: #49943
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Raz Luvaton <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: LiviaMedeiros <[email protected]>
targos pushed a commit that referenced this pull request Nov 11, 2023
@cjihrig @targos
test_runner: replace spurious if with else
10b35cf
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: #48915
PR-URL: #49943
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Raz Luvaton <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: LiviaMedeiros <[email protected]>
@targos targos added backported-to-v20.x and removed backport-open-v20.x labels Nov 12, 2023
targos pushed a commit that referenced this pull request Nov 27, 2023
@rluvaton @targos
test_runner: cleanup test timeout abort listener
67d7fad
fix #48475

PR-URL: #48915
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
targos pushed a commit that referenced this pull request Nov 27, 2023
@rluvaton @targos
test: remove --no-warnings flag in test_runner fixtures
7e714e6
no longer needed after #48915 fix

PR-URL: #48989
Backport-PR-URL: #49225
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
targos pushed a commit that referenced this pull request Nov 27, 2023
@cjihrig @targos
test_runner: replace spurious if with else
1d9c371
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: #48915
PR-URL: #49943
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Raz Luvaton <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: LiviaMedeiros <[email protected]>
@targos targos mentioned this pull request Nov 28, 2023
v18.19.0 release proposal #50953
Merged
debadree25 pushed a commit to debadree25/node that referenced this pull request Apr 15, 2024
@cjihrig @debadree25
test_runner: replace spurious if with else
0025722
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: nodejs#48915
PR-URL: nodejs#49943
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Raz Luvaton <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: LiviaMedeiros <[email protected]>
sercher added a commit to sercher/graaljs that referenced this pull request Apr 25, 2024
@sercher
test_runner: cleanup test timeout abort listener
41ad677
fix #48475

PR-URL: nodejs/node#48915
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
sercher added a commit to sercher/graaljs that referenced this pull request Apr 25, 2024
@sercher
test_runner: replace spurious if with else
ad9cae4
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: nodejs/node#48915
PR-URL: nodejs/node#49943
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Raz Luvaton <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: LiviaMedeiros <[email protected]>
sercher added a commit to sercher/graaljs that referenced this pull request Apr 25, 2024
@sercher
test_runner: cleanup test timeout abort listener
5316841
fix #48475

PR-URL: nodejs/node#48915
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
sercher added a commit to sercher/graaljs that referenced this pull request Apr 25, 2024
@sercher
test_runner: replace spurious if with else
f0691a1
There is an `if` statement that likely should have been
an `else` in the original PR.

Refs: nodejs/node#48915
PR-URL: nodejs/node#49943
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Raz Luvaton <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: LiviaMedeiros <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ljharb ljharb ljharb left review comments
@benjamingr benjamingr benjamingr approved these changes
@MoLow MoLow MoLow approved these changes
@atlowChemi atlowChemi atlowChemi approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

author ready PRs with CI started, the required approvals, and no outstanding review comments. commit-queue-squash PRs the Commit Queue should land as one squashed commit. needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

node:test beforeEach and afterEach generate MaxListenersExceededWarning

Uh oh!

There was an error while loading. Please reload this page.

9 participants

@rluvaton @nodejs-github-bot @MoLow @benjamingr @atlowChemi @RafaelGSS @ljharb @targos @debadree25
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.