Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: useDeprecatedNextContext no longer available #6596

Merged
merged 1 commit into from Sep 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion api_guard/dist/types/index.d.ts
Expand Up @@ -278,7 +278,6 @@ export interface GlobalConfig {
Promise?: PromiseConstructorLike;
onStoppedNotification: ((notification: ObservableNotification<any>, subscriber: Subscriber<any>) => void) | null;
onUnhandledError: ((err: any) => void) | null;
useDeprecatedNextContext: boolean;
useDeprecatedSynchronousErrorHandling: boolean;
}

Expand Down
63 changes: 0 additions & 63 deletions spec/Subscriber-spec.ts
Expand Up @@ -180,69 +180,6 @@ describe('Subscriber', () => {
expect(consumer.valuesProcessed).not.to.equal(['new', 'new']);
});

describe('deprecated next context mode', () => {
beforeEach(() => {
config.useDeprecatedNextContext = true;
});

afterEach(() => {
config.useDeprecatedNextContext = false;
});

it('should allow changing the context of `this` in a POJO subscriber', () => {
const results: any[] = [];

const source = new Observable<number>(subscriber => {
for (let i = 0; i < 10 && !subscriber.closed; i++) {
subscriber.next(i);
}
subscriber.complete();

return () => {
results.push('teardown');
}
});

source.subscribe({
next: function (this: any, value) {
expect(this.unsubscribe).to.be.a('function');
results.push(value);
if (value === 3) {
this.unsubscribe();
}
},
complete() {
throw new Error('should not be called');
}
});

expect(results).to.deep.equal([0, 1, 2, 3, 'teardown'])
});

it('should NOT break this context on next methods from unfortunate consumers', () => {
// This is a contrived class to illustrate that we can pass another
// object that is "observer shaped"
class CustomConsumer {
valuesProcessed: string[] = [];

// In here, we access instance state and alter it.
next(value: string) {
if (value === 'reset') {
this.valuesProcessed = [];
} else {
this.valuesProcessed.push(value);
}
}
};

const consumer = new CustomConsumer();

of('old', 'old', 'reset', 'new', 'new').subscribe(consumer);

expect(consumer.valuesProcessed).not.to.equal(['new', 'new']);
});
});

const FinalizationRegistry = (global as any).FinalizationRegistry;
if (FinalizationRegistry && global.gc) {

Expand Down
17 changes: 3 additions & 14 deletions src/internal/Subscriber.ts
Expand Up @@ -155,20 +155,9 @@ export class SafeSubscriber<T> extends Subscriber<T> {
// going to put them all in a new destination with ensured methods
// for `next`, `error`, and `complete`. That's part of what makes this
// the "Safe" Subscriber.
({ next, error, complete } = observerOrNext);
let context: any;
if (this && config.useDeprecatedNextContext) {
// This is a deprecated path that made `this.unsubscribe()` available in
// next handler functions passed to subscribe. This only exists behind a flag
// now, as it is *very* slow.
context = Object.create(observerOrNext);
context.unsubscribe = () => this.unsubscribe();
} else {
context = observerOrNext;
}
next = next?.bind(context);
error = error?.bind(context);
complete = complete?.bind(context);
next = observerOrNext.next?.bind(observerOrNext);
error = observerOrNext.error?.bind(observerOrNext);
complete = observerOrNext.complete?.bind(observerOrNext);
}

// Once we set the destination, the superclass `Subscriber` will
Expand Down
17 changes: 0 additions & 17 deletions src/internal/config.ts
Expand Up @@ -10,7 +10,6 @@ export const config: GlobalConfig = {
onStoppedNotification: null,
Promise: undefined,
useDeprecatedSynchronousErrorHandling: false,
useDeprecatedNextContext: false,
};

/**
Expand Down Expand Up @@ -65,20 +64,4 @@ export interface GlobalConfig {
* behaviors described above. Will be removed in v8.
*/
useDeprecatedSynchronousErrorHandling: boolean;

/**
* If true, enables an as-of-yet undocumented feature from v5: The ability to access
* `unsubscribe()` via `this` context in `next` functions created in observers passed
* to `subscribe`.
*
* This is being removed because the performance was severely problematic, and it could also cause
* issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have
* their `this` context overwritten.
*
* @deprecated As of version 8, RxJS will no longer support altering the
* context of next functions provided as part of an observer to Subscribe. Instead,
* you will have access to a subscription or a signal or token that will allow you to do things like
* unsubscribe and test closed status. Will be removed in v8.
*/
useDeprecatedNextContext: boolean;
}