-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7660 from apollographql/backport-symbol-species-fix
Backport v3.4 Symbol.species fix for Concast and ObservableQuery.
- Loading branch information
Showing
10 changed files
with
140 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { Observable } from "../Observable"; | ||
import { Concast } from "../Concast"; | ||
|
||
function toArrayPromise<T>(observable: Observable<T>): Promise<T[]> { | ||
return new Promise<T[]>((resolve, reject) => { | ||
const values: T[] = []; | ||
observable.subscribe({ | ||
next(value) { | ||
values.push(value); | ||
}, | ||
error: reject, | ||
complete() { | ||
resolve(values); | ||
}, | ||
}); | ||
}); | ||
} | ||
|
||
describe("Observable subclassing", () => { | ||
it("Symbol.species is defined for Concast subclass", () => { | ||
const concast = new Concast([ | ||
Observable.of(1, 2, 3), | ||
Observable.of(4, 5), | ||
]); | ||
expect(concast).toBeInstanceOf(Concast); | ||
|
||
const mapped = concast.map(n => n * 2); | ||
expect(mapped).toBeInstanceOf(Observable); | ||
expect(mapped).not.toBeInstanceOf(Concast); | ||
|
||
return toArrayPromise(mapped).then(doubles => { | ||
expect(doubles).toEqual([2, 4, 6, 8, 10]); | ||
}); | ||
}); | ||
|
||
it("Inherited Concast.of static method returns a Concast", () => { | ||
const concast = Concast.of("asdf", "qwer", "zxcv"); | ||
expect(concast).toBeInstanceOf(Observable); | ||
expect(concast).toBeInstanceOf(Concast); | ||
|
||
return toArrayPromise(concast).then(values => { | ||
expect(values).toEqual(["asdf", "qwer", "zxcv"]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Observable } from "./Observable"; | ||
|
||
// Generic implementations of Observable.prototype methods like map and | ||
// filter need to know how to create a new Observable from an Observable | ||
// subclass (like Concast or ObservableQuery). Those methods assume | ||
// (perhaps unwisely?) that they can call the subtype's constructor with a | ||
// Subscriber function, even though the subclass constructor might expect | ||
// different parameters. Defining this static Symbol.species property on | ||
// the subclass is a hint to generic Observable code to use the default | ||
// constructor instead of trying to do `new Subclass(observer => ...)`. | ||
export function fixObservableSubclass< | ||
S extends new (...args: any[]) => Observable<any>, | ||
>(subclass: S): S { | ||
function set(key: symbol | string) { | ||
// Object.defineProperty is necessary because the Symbol.species | ||
// property is a getter by default in modern JS environments, so we | ||
// can't assign to it with a normal assignment expression. | ||
Object.defineProperty(subclass, key, { value: Observable }); | ||
} | ||
if (typeof Symbol === "function" && Symbol.species) { | ||
set(Symbol.species); | ||
} | ||
// The "@@species" string is used as a fake Symbol.species value in some | ||
// polyfill systems (including the SymbolSpecies variable used by | ||
// zen-observable), so we should set it as well, to be safe. | ||
set("@@species"); | ||
return subclass; | ||
} |