Skip to content

Commit 930889c

Browse files
committed
refactor: reduce bundle size
1 parent 8a37d79 commit 930889c

7 files changed

Lines changed: 92 additions & 65 deletions

File tree

mangle-cache.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1-
{}
1+
{
2+
"addDep_": "d",
3+
"data_": "a",
4+
"delete_": "l",
5+
"dependents_": "n",
6+
"deps_": "p",
7+
"equal_": "e",
8+
"multi_": "m",
9+
"notify_": "y",
10+
"onReaction_": "o",
11+
"single_": "s",
12+
"task_": "k",
13+
"upsert_": "u"
14+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"test:coverage": "vitest --coverage",
2727
"test:ci": "vitest --coverage",
2828
"build": "tsup",
29-
"build:min": "MINIFY=true tsup && echo '' && gzip-size dist/index.mjs dist/index.js",
29+
"build:min": "MINIFY=true tsup --env.NODE_ENV production && echo '' && gzip-size dist/index.mjs dist/index.js",
3030
"release": "commit-and-tag-version"
3131
},
3232
"keywords": [

src/batch.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
1+
import { context } from "./context";
12
import { UNIQUE_VALUE } from "./utils";
23

3-
export const BATCH_SCOPE = /* @__PURE__ */ Symbol.for("[@embra/reactivity/batch]");
4-
export type BATCH_SCOPE = typeof BATCH_SCOPE;
5-
6-
declare const globalThis: {
7-
[BATCH_SCOPE]?: boolean;
8-
};
9-
104
export type BatchTask<O extends object = object> = O & {
11-
[BATCH_SCOPE]: () => void;
5+
task_: () => void;
126
};
137

14-
export const tasks = /* @__PURE__ */ new Set<BatchTask>();
8+
export const tasks: Set<BatchTask> = /* @__PURE__ */ (() => context.tasks_)();
159

1610
export const toTask = <T extends object>(target: T, fn: () => void): BatchTask<T> => (
17-
((target as BatchTask)[BATCH_SCOPE] = fn), target as BatchTask<T>
11+
((target as BatchTask).task_ = fn), target as BatchTask<T>
1812
);
1913

20-
export const batchStart = (): boolean => (globalThis[BATCH_SCOPE] ? false : (globalThis[BATCH_SCOPE] = true));
14+
export const batchStart = (): boolean => !context.batching_ && (context.batching_ = true);
2115

2216
export const batchFlush = (): void => {
23-
if (globalThis[BATCH_SCOPE]) {
17+
if (context.batching_) {
2418
let error: unknown = UNIQUE_VALUE;
2519
for (const task of tasks) {
2620
tasks.delete(task);
2721
try {
28-
task[BATCH_SCOPE]();
22+
task.task_();
2923
} catch (e) {
3024
error = e;
3125
}
3226
}
3327

34-
globalThis[BATCH_SCOPE] = false;
28+
context.batching_ = false;
3529

3630
if (error !== UNIQUE_VALUE) {
3731
throw error;

src/collections/reactiveMap.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { batch, type BatchTask, tasks, toTask } from "../batch";
1+
import { batchFlush, batchStart, type BatchTask, tasks, toTask } from "../batch";
22
import { type AddEventListener, event, send, size } from "../event";
33
import { writable } from "../readable";
44
import { type Disposer, type OwnedWritable, type Readable } from "../typings";
@@ -24,16 +24,16 @@ export class OwnedReactiveMap<K, V> extends Map<K, V> {
2424
* @returns A disposer function to unsubscribe from the event.
2525
*/
2626
public onChanged(fn: (changed: ReactiveMapChanged<K, V>) => void): Disposer {
27-
return (this._onChanged_ ??= toTask(event({ delete: new Set(), upsert: new Map() }), () => {
27+
return (this._onChanged_ ??= toTask(event({ delete_: new Set(), upsert_: new Map() }), () => {
2828
if (this._onChanged_ && size(this._onChanged_)) {
2929
const { data_ } = this._onChanged_;
30-
if (data_.upsert.size > 0 || data_.delete.size > 0) {
30+
if (data_.upsert_.size > 0 || data_.delete_.size > 0) {
3131
const changedData = {
32-
upsert: [...data_.upsert],
33-
delete: [...data_.delete],
32+
upsert: [...data_.upsert_],
33+
delete: [...data_.delete_],
3434
};
35-
data_.upsert.clear();
36-
data_.delete.clear();
35+
data_.upsert_.clear();
36+
data_.delete_.clear();
3737
send(this._onChanged_, changedData);
3838
}
3939
} else {
@@ -77,11 +77,11 @@ export class OwnedReactiveMap<K, V> extends Map<K, V> {
7777
super();
7878

7979
if (entries) {
80-
batch(() => {
81-
for (const [key, value] of entries) {
82-
this.set(key, value);
83-
}
84-
});
80+
const isBatchTop = batchStart();
81+
for (const [key, value] of entries) {
82+
this.set(key, value);
83+
}
84+
isBatchTop && batchFlush();
8585
}
8686
}
8787

@@ -98,9 +98,9 @@ export class OwnedReactiveMap<K, V> extends Map<K, V> {
9898
data_.add(value);
9999
}
100100
if (data_.size) {
101-
batch(() => {
102-
tasks.add(this._onDisposeValue_!);
103-
});
101+
const isBatchTop = batchStart();
102+
tasks.add(this._onDisposeValue_!);
103+
isBatchTop && batchFlush();
104104
}
105105
}
106106
this._$ = this._onChanged_ = this._onDisposeValue_ = undefined;
@@ -110,60 +110,68 @@ export class OwnedReactiveMap<K, V> extends Map<K, V> {
110110
if (this.has(key)) {
111111
const oldValue = this.get(key)!;
112112
if (!strictEqual(oldValue, value)) {
113+
const isBatchTop = batchStart();
113114
// task added in this._upsert_
114115
this._onDisposeValue_?.data_.add(oldValue);
115116
this._upsert_(key, value);
117+
isBatchTop && batchFlush();
116118
}
117119
} else {
120+
const isBatchTop = batchStart();
118121
this._upsert_(key, value);
122+
isBatchTop && batchFlush();
119123
}
120124
return this;
121125
}
122126

123127
public override delete(key: K): boolean {
124128
if (this.has(key)) {
129+
const isBatchTop = batchStart();
125130
if (this._onDisposeValue_) {
126131
this._onDisposeValue_.data_.add(this.get(key)!);
127132
tasks.add(this._onDisposeValue_);
128133
}
129134
if (this._onChanged_) {
130-
this._onChanged_.data_.delete.add(key);
131-
this._onChanged_.data_.upsert.delete(key);
135+
this._onChanged_.data_.delete_.add(key);
136+
this._onChanged_.data_.upsert_.delete(key);
132137
tasks.add(this._onChanged_);
133138
}
134139
this._notify_();
140+
isBatchTop && batchFlush();
135141
}
136142
return super.delete(key);
137143
}
138144

139145
public override clear(): void {
140146
if (this.size) {
147+
const isBatchTop = batchStart();
141148
if (this._onDisposeValue_ || this._onChanged_) {
142149
for (const [key, value] of this) {
143150
if (this._onDisposeValue_) {
144151
this._onDisposeValue_.data_.add(value);
145152
tasks.add(this._onDisposeValue_);
146153
}
147154
if (this._onChanged_) {
148-
this._onChanged_.data_.delete.add(key);
149-
this._onChanged_.data_.upsert.delete(key);
155+
this._onChanged_.data_.delete_.add(key);
156+
this._onChanged_.data_.upsert_.delete(key);
150157
tasks.add(this._onChanged_);
151158
}
152159
}
153160
}
154161
super.clear();
155162
this._notify_();
163+
isBatchTop && batchFlush();
156164
}
157165
}
158166

159167
public rename(key: K, newKey: K): void {
160-
batch(() => {
161-
if (this.has(key)) {
162-
const value = this.get(key)!;
163-
this.delete(key);
164-
this.set(newKey, value);
165-
}
166-
});
168+
if (this.has(key)) {
169+
const isBatchTop = batchStart();
170+
const value = this.get(key)!;
171+
this.delete(key);
172+
this.set(newKey, value);
173+
isBatchTop && batchFlush();
174+
}
167175
}
168176

169177
/**
@@ -179,8 +187,8 @@ export class OwnedReactiveMap<K, V> extends Map<K, V> {
179187
AddEventListener<
180188
ReactiveMapChanged<K, V>,
181189
{
182-
readonly upsert: Map<K, V>;
183-
readonly delete: Set<K>;
190+
readonly upsert_: Map<K, V>;
191+
readonly delete_: Set<K>;
184192
}
185193
>
186194
>;
@@ -195,8 +203,8 @@ export class OwnedReactiveMap<K, V> extends Map<K, V> {
195203
tasks.add(this._onDisposeValue_);
196204
}
197205
if (this._onChanged_) {
198-
this._onChanged_.data_.upsert.set(key, value);
199-
this._onChanged_.data_.delete.delete(key);
206+
this._onChanged_.data_.upsert_.set(key, value);
207+
this._onChanged_.data_.delete_.delete(key);
200208
tasks.add(this._onChanged_);
201209
}
202210
super.set(key, value);

src/context.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { type BatchTask } from "./batch";
2+
import { BRAND } from "./utils";
3+
4+
export interface Context {
5+
batching_: boolean;
6+
readonly tasks_: Set<BatchTask>;
7+
}
8+
9+
declare const globalThis: {
10+
[BRAND]?: Context;
11+
};
12+
13+
export const context: Context = /* @__PURE__ */ (() =>
14+
(globalThis[BRAND] ??= {
15+
batching_: false,
16+
tasks_: new Set<BatchTask>(),
17+
}))();

src/readable.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { batchFlush, batchStart, BATCH_SCOPE, tasks } from "./batch";
1+
import { batchFlush, batchStart, tasks } from "./batch";
22
import {
33
type OwnedReadable,
44
type OwnedWritable,
@@ -72,11 +72,6 @@ export class ReadableImpl<TValue = any> {
7272
*/
7373
public deps_?: Map<ReadableImpl, Version>;
7474

75-
/**
76-
* @internal
77-
*/
78-
public eager_?: boolean;
79-
8075
/**
8176
* @internal
8277
*/
@@ -89,7 +84,7 @@ export class ReadableImpl<TValue = any> {
8984
/**
9085
* @internal
9186
*/
92-
public subs_?: Set<Subscriber<TValue>>;
87+
private _subs_?: Set<Subscriber<TValue>>;
9388

9489
public get $version(): Version {
9590
this.get();
@@ -107,7 +102,7 @@ export class ReadableImpl<TValue = any> {
107102
/**
108103
* @internal
109104
*/
110-
private lastSubInvokeVersion_: Version = -1;
105+
private _lastSubInvokeVersion_: Version = -1;
111106

112107
/**
113108
* @internal
@@ -156,12 +151,12 @@ export class ReadableImpl<TValue = any> {
156151
}
157152

158153
/** @internal */
159-
public [BATCH_SCOPE](): void {
154+
public task_(): void {
160155
let error: unknown = UNIQUE_VALUE;
161-
if (this.subs_?.size && this.lastSubInvokeVersion_ !== this.$version) {
162-
this.lastSubInvokeVersion_ = this.$version;
156+
if (this._subs_?.size && this._lastSubInvokeVersion_ !== this.$version) {
157+
this._lastSubInvokeVersion_ = this.$version;
163158
const value = this.get();
164-
for (const sub of this.subs_) {
159+
for (const sub of this._subs_) {
165160
try {
166161
sub(value);
167162
} catch (e) {
@@ -276,11 +271,11 @@ export class ReadableImpl<TValue = any> {
276271

277272
/** @internal */
278273
public onReaction_(subscriber: Subscriber<TValue>): void {
279-
if (!this.subs_?.size) {
274+
if (!this._subs_?.size) {
280275
// start tracking last first on first subscription
281-
this.lastSubInvokeVersion_ = this.$version;
276+
this._lastSubInvokeVersion_ = this.$version;
282277
}
283-
(this.subs_ ??= new Set()).add(subscriber);
278+
(this._subs_ ??= new Set()).add(subscriber);
284279
}
285280

286281
public reaction(subscriber: Subscriber<TValue>): Disposer {
@@ -329,11 +324,11 @@ export class ReadableImpl<TValue = any> {
329324
}
330325

331326
public unsubscribe(subscriber: (...args: any[]) => any): void {
332-
this.subs_?.delete(subscriber);
327+
this._subs_?.delete(subscriber);
333328
}
334329

335330
public unsubscribeAll(): void {
336-
this.subs_?.clear();
331+
this._subs_?.clear();
337332
}
338333

339334
public valueOf(): TValue {

src/watch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { batch, batchFlush, batchStart, BATCH_SCOPE, tasks } from "./batch";
1+
import { batch, batchFlush, batchStart, tasks } from "./batch";
22
import { type Disposer, type Get, type Readable } from "./typings";
33
import { identity, isReadable, unsubscribe } from "./utils";
44

@@ -85,7 +85,7 @@ export const watch = (effect: WatchEffect): Disposer => {
8585
isBatchTop && batchFlush();
8686
}
8787
};
88-
runner[BATCH_SCOPE] = runner;
88+
runner.task_ = runner;
8989

9090
runner();
9191

0 commit comments

Comments
 (0)