@atlaskit/editor-synced-block-provider 4.3.1 → 4.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +33 -73
- package/CHANGELOG.md +21 -0
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +45 -37
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +86 -40
- package/dist/cjs/store-manager/syncBlockStoreManager.js +125 -116
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +6 -1
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +36 -2
- package/dist/es2019/store-manager/syncBlockStoreManager.js +91 -91
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +45 -37
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +86 -40
- package/dist/esm/store-manager/syncBlockStoreManager.js +125 -116
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +3 -1
- package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +6 -2
- package/dist/types/store-manager/syncBlockStoreManager.d.ts +3 -1
- package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +3 -1
- package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +6 -2
- package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +3 -1
- package/package.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Synced Block Provider — Developer Agent Guide
|
|
2
2
|
|
|
3
|
-
> **Package**: `@atlaskit/editor-synced-block-provider`
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
3
|
+
> **Package**: `@atlaskit/editor-synced-block-provider`
|
|
4
|
+
>
|
|
5
|
+
> **For workflow guidance, debugging, and cross-package task guides, load the `synced-blocks` skill:**
|
|
6
|
+
> `get_skill(skill_name_or_path="platform/packages/editor/.rovodev/skills/synced-blocks/SKILL.md")`
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -19,29 +19,29 @@ plugin and the renderer across Confluence and Jira.
|
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
src/
|
|
22
|
-
├── index.ts
|
|
22
|
+
├── index.ts # Barrel export
|
|
23
23
|
├── store-manager/
|
|
24
|
-
│ ├── syncBlockStoreManager.ts
|
|
25
|
-
│ ├── referenceSyncBlockStoreManager.ts
|
|
26
|
-
│ └── sourceSyncBlockStoreManager.ts
|
|
24
|
+
│ ├── syncBlockStoreManager.ts # Parent coordinator for source + reference managers
|
|
25
|
+
│ ├── referenceSyncBlockStoreManager.ts # Reference block lifecycle, cache, subscriptions, flush
|
|
26
|
+
│ └── sourceSyncBlockStoreManager.ts # Source block create, update, delete, flush
|
|
27
27
|
├── clients/
|
|
28
28
|
│ ├── block-service/
|
|
29
|
-
│ │ ├── blockService.ts
|
|
30
|
-
│ │ └── ari.ts
|
|
29
|
+
│ │ ├── blockService.ts # Block service API client (fetch, batch, CRUD)
|
|
30
|
+
│ │ └── ari.ts # Block ARI generation/parsing
|
|
31
31
|
│ ├── confluence/
|
|
32
|
-
│ │ ├── ari.ts
|
|
33
|
-
│ │ └── fetchMediaToken.ts
|
|
32
|
+
│ │ ├── ari.ts # Confluence page ARI generation/parsing
|
|
33
|
+
│ │ └── fetchMediaToken.ts # Media token fetching via GraphQL (MediaUploadTokenQuery)
|
|
34
34
|
│ └── jira/
|
|
35
|
-
│ └── ari.ts
|
|
35
|
+
│ └── ari.ts # Jira work item ARI generation/parsing
|
|
36
36
|
├── providers/
|
|
37
37
|
│ └── block-service/
|
|
38
|
-
│ └── blockServiceAPI.ts
|
|
39
|
-
└── types/
|
|
38
|
+
│ └── blockServiceAPI.ts # Provider factory and API helpers
|
|
39
|
+
└── types/ # Shared types
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
## Key
|
|
44
|
+
## Key Exports and Types
|
|
45
45
|
|
|
46
46
|
### Store Manager Hierarchy
|
|
47
47
|
|
|
@@ -49,81 +49,41 @@ src/
|
|
|
49
49
|
SyncBlockStoreManager (parent coordinator)
|
|
50
50
|
├── SourceSyncBlockStoreManager
|
|
51
51
|
│ ├── create(content) → Block Service API → returns resourceId
|
|
52
|
-
│ ├──
|
|
53
|
-
│ ├──
|
|
54
|
-
│
|
|
52
|
+
│ ├── updateSyncBlockData(node) → marks isDirty, caches content
|
|
53
|
+
│ ├── flush() → persist all dirty changes to backend
|
|
54
|
+
│ ├── hasUnsavedChanges() → checks isDirty + hasReceivedContentChange
|
|
55
|
+
│ └── delete(resourceId) → soft delete with confirmation
|
|
55
56
|
└── ReferenceSyncBlockStoreManager
|
|
56
57
|
├── fetchSyncBlocksData(nodes) → batch fetch with deduplication
|
|
57
|
-
├── subscribeToSyncBlock(resourceId,
|
|
58
|
+
├── subscribeToSyncBlock(resourceId, callback) → AGG WebSocket
|
|
58
59
|
├── fetchSyncBlockSourceInfo(resourceId) → title, URL metadata
|
|
59
|
-
├── getFromCache(resourceId) → retrieve cached data
|
|
60
|
-
├── flush() → save reference changes to backend
|
|
61
60
|
└── destroy() → cleanup subscriptions and batchers
|
|
62
61
|
```
|
|
63
62
|
|
|
64
|
-
### ARI
|
|
63
|
+
### ARI Utilities
|
|
65
64
|
|
|
66
|
-
| Function |
|
|
67
|
-
| ------------------------------------------------------------ |
|
|
68
|
-
| `generateBlockAri({cloudId, parentId, product, resourceId})` |
|
|
69
|
-
| `generateBlockAriFromReference({cloudId, resourceId})` |
|
|
70
|
-
| `getConfluencePageAri({pageId, cloudId, pageType})` | Confluence page
|
|
71
|
-
| `getJiraWorkItemAri({cloudId, workItemId})` | Jira issue
|
|
72
|
-
| `getJiraWorkItemIdFromAri(ari)` | Extract issue ID from ARI | — |
|
|
65
|
+
| Function | Purpose |
|
|
66
|
+
| ------------------------------------------------------------ | -------------------------- |
|
|
67
|
+
| `generateBlockAri({cloudId, parentId, product, resourceId})` | Generate source block ARI |
|
|
68
|
+
| `generateBlockAriFromReference({cloudId, resourceId})` | Generate reference ARI |
|
|
69
|
+
| `getConfluencePageAri({pageId, cloudId, pageType})` | Confluence page ARI |
|
|
70
|
+
| `getJiraWorkItemAri({cloudId, workItemId})` | Jira issue ARI |
|
|
73
71
|
|
|
74
72
|
### Block Service API
|
|
75
73
|
|
|
76
74
|
The client in `clients/block-service/blockService.ts` communicates via GraphQL at
|
|
77
|
-
`/gateway/api/graphql`:
|
|
78
|
-
|
|
79
|
-
- **Fetch**: Single or batch block content retrieval
|
|
80
|
-
- **Create**: Register new source block with content
|
|
81
|
-
- **Update**: Push content changes (debounced 3s)
|
|
82
|
-
- **Delete**: Soft delete a source block
|
|
83
|
-
- **Source Info**: Fetch metadata (source page title, URL)
|
|
84
|
-
- **References Info**: Fetch list of locations referencing a block
|
|
75
|
+
`/gateway/api/graphql`: Fetch, Create, Update (debounced 3s), Delete, Source Info, References Info.
|
|
85
76
|
|
|
86
77
|
### Media Token Fetching
|
|
87
78
|
|
|
88
79
|
`fetchMediaToken(contentId)` → GraphQL `MediaUploadTokenQuery` → returns
|
|
89
80
|
`{token, config: {clientId, fileStoreUrl}, collectionId}`
|
|
90
81
|
|
|
91
|
-
Used when synced blocks contain media (images, files) — the reference needs a valid token to render
|
|
92
|
-
media from the source page.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Common Tasks
|
|
97
|
-
|
|
98
|
-
### Adding a new API method
|
|
99
|
-
|
|
100
|
-
1. Add the GraphQL query/mutation in `clients/block-service/blockService.ts`
|
|
101
|
-
2. Expose it through the appropriate store manager
|
|
102
|
-
3. Export from `src/index.ts` if needed by product integrations
|
|
103
|
-
4. Add tests in `editor-synced-block-provider-tests`
|
|
104
|
-
|
|
105
|
-
### Debugging data issues
|
|
106
|
-
|
|
107
|
-
1. Check `ReferenceSyncBlockStoreManager` cache state
|
|
108
|
-
2. Verify ARI format matches expected pattern for the product
|
|
109
|
-
3. Check Block Service API responses in network tab (look for `/gateway/api/graphql`)
|
|
110
|
-
4. Use analytics:
|
|
111
|
-
[HOW-TO: Debug errors](https://hello.atlassian.net/wiki/spaces/egcuc/pages/6342760320)
|
|
112
|
-
|
|
113
|
-
### Adding support for a new product
|
|
114
|
-
|
|
115
|
-
1. Create ARI utilities in `clients/{product}/ari.ts`
|
|
116
|
-
2. Ensure `generateBlockAri` supports the new product type
|
|
117
|
-
3. Add media token fetching if the product has media content
|
|
118
|
-
4. Update store managers if the product has unique lifecycle requirements
|
|
119
|
-
|
|
120
82
|
---
|
|
121
83
|
|
|
122
84
|
## Related Packages
|
|
123
85
|
|
|
124
|
-
- **Plugin**: `platform/packages/editor/editor-plugin-synced-block/`
|
|
125
|
-
- **Renderer**: `platform/packages/editor/editor-synced-block-renderer/`
|
|
126
|
-
- **Confluence**: `confluence/next/packages/fabric-providers/src/SyncedBlockProvider.ts`
|
|
127
|
-
|
|
128
|
-
- **Jira**: `jira/src/packages/issue/issue-view-synced-block-provider/` — wraps this provider with
|
|
129
|
-
Relay
|
|
86
|
+
- **Plugin**: `platform/packages/editor/editor-plugin-synced-block/`
|
|
87
|
+
- **Renderer**: `platform/packages/editor/editor-synced-block-renderer/`
|
|
88
|
+
- **Confluence**: `confluence/next/packages/fabric-providers/src/SyncedBlockProvider.ts`
|
|
89
|
+
- **Jira**: `jira/src/packages/issue/issue-view-synced-block-provider/`
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @atlaskit/editor-synced-block-provider
|
|
2
2
|
|
|
3
|
+
## 4.3.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`15deee785151b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/15deee785151b) -
|
|
8
|
+
EDITOR-6174 Pass node to createBodiedSyncBlockNode to cache content on creation, preventing false
|
|
9
|
+
unsaved changes on page refresh
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 4.3.2
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`eaeabd907b737`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/eaeabd907b737) -
|
|
17
|
+
Move unregistered references logic into a separate method.
|
|
18
|
+
- [`38e89dd6515da`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/38e89dd6515da) -
|
|
19
|
+
Disable synced block write operations (create, update, delete, flush) when the editor is in view
|
|
20
|
+
mode, gated behind platform_synced_block_patch_8. This prevents unintended block service mutations
|
|
21
|
+
(e.g. deletion modals, data loss) when the editor is used in read-only contexts such as Version
|
|
22
|
+
History.
|
|
23
|
+
|
|
3
24
|
## 4.3.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -13,6 +13,7 @@ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/creat
|
|
|
13
13
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
14
14
|
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
15
15
|
var _monitoring = require("@atlaskit/editor-common/monitoring");
|
|
16
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
16
17
|
var _types = require("../common/types");
|
|
17
18
|
var _errorHandling = require("../utils/errorHandling");
|
|
18
19
|
var _experienceTracking = require("../utils/experienceTracking");
|
|
@@ -37,7 +38,7 @@ var CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
|
37
38
|
var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
38
39
|
// Track the setTimeout handle for queued flush so we can cancel it on destroy
|
|
39
40
|
|
|
40
|
-
function ReferenceSyncBlockStoreManager(dataProvider) {
|
|
41
|
+
function ReferenceSyncBlockStoreManager(dataProvider, viewMode) {
|
|
41
42
|
var _this = this,
|
|
42
43
|
_this$dataProvider;
|
|
43
44
|
(0, _classCallCheck2.default)(this, ReferenceSyncBlockStoreManager);
|
|
@@ -52,6 +53,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
52
53
|
// Track if another flush is needed after the current one completes
|
|
53
54
|
(0, _defineProperty2.default)(this, "flushNeededAfterCurrent", false);
|
|
54
55
|
this.dataProvider = dataProvider;
|
|
56
|
+
this.viewMode = viewMode;
|
|
55
57
|
this.syncBlockFetchDataRequests = new Map();
|
|
56
58
|
this.syncBlockSourceInfoRequests = new Map();
|
|
57
59
|
this.newlyAddedSyncBlocks = new Set();
|
|
@@ -702,14 +704,20 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
702
704
|
return _regenerator.default.wrap(function _callee3$(_context4) {
|
|
703
705
|
while (1) switch (_context4.prev = _context4.next) {
|
|
704
706
|
case 0:
|
|
705
|
-
if (this.
|
|
707
|
+
if (!(this.viewMode === 'view' && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_8'))) {
|
|
706
708
|
_context4.next = 2;
|
|
707
709
|
break;
|
|
708
710
|
}
|
|
709
|
-
return _context4.abrupt("return",
|
|
711
|
+
return _context4.abrupt("return", false);
|
|
710
712
|
case 2:
|
|
713
|
+
if (this.isCacheDirty) {
|
|
714
|
+
_context4.next = 4;
|
|
715
|
+
break;
|
|
716
|
+
}
|
|
717
|
+
return _context4.abrupt("return", true);
|
|
718
|
+
case 4:
|
|
711
719
|
if (!this.isFlushInProgress) {
|
|
712
|
-
_context4.next =
|
|
720
|
+
_context4.next = 9;
|
|
713
721
|
break;
|
|
714
722
|
}
|
|
715
723
|
// Mark that another flush is needed after the current one completes
|
|
@@ -717,22 +725,22 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
717
725
|
|
|
718
726
|
// We return true here because we know the pending flush will handle the dirty cache
|
|
719
727
|
return _context4.abrupt("return", true);
|
|
720
|
-
case
|
|
728
|
+
case 9:
|
|
721
729
|
this.isFlushInProgress = true;
|
|
722
|
-
case
|
|
730
|
+
case 10:
|
|
723
731
|
success = true; // a copy of the subscriptions STRUCTURE (without the callbacks)
|
|
724
732
|
// To be saved as the last flushed structure if the flush is successful
|
|
725
733
|
syncedBlocksToFlush = {};
|
|
726
|
-
_context4.prev =
|
|
734
|
+
_context4.prev = 12;
|
|
727
735
|
if (this.dataProvider) {
|
|
728
|
-
_context4.next =
|
|
736
|
+
_context4.next = 15;
|
|
729
737
|
break;
|
|
730
738
|
}
|
|
731
739
|
throw new Error('Data provider not set');
|
|
732
|
-
case
|
|
740
|
+
case 15:
|
|
733
741
|
blocks = []; // First, build the complete subscription structure
|
|
734
742
|
_iterator = _createForOfIteratorHelper(this._subscriptionManager.getSubscriptions().entries());
|
|
735
|
-
_context4.prev =
|
|
743
|
+
_context4.prev = 17;
|
|
736
744
|
_loop = /*#__PURE__*/_regenerator.default.mark(function _loop() {
|
|
737
745
|
var _step$value, resourceId, callbacks;
|
|
738
746
|
return _regenerator.default.wrap(function _loop$(_context3) {
|
|
@@ -754,34 +762,34 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
754
762
|
}, _loop);
|
|
755
763
|
});
|
|
756
764
|
_iterator.s();
|
|
757
|
-
case
|
|
765
|
+
case 20:
|
|
758
766
|
if ((_step = _iterator.n()).done) {
|
|
759
|
-
_context4.next =
|
|
767
|
+
_context4.next = 24;
|
|
760
768
|
break;
|
|
761
769
|
}
|
|
762
|
-
return _context4.delegateYield(_loop(), "t0",
|
|
763
|
-
case 20:
|
|
764
|
-
_context4.next = 18;
|
|
765
|
-
break;
|
|
770
|
+
return _context4.delegateYield(_loop(), "t0", 22);
|
|
766
771
|
case 22:
|
|
767
|
-
_context4.next =
|
|
772
|
+
_context4.next = 20;
|
|
768
773
|
break;
|
|
769
774
|
case 24:
|
|
770
|
-
_context4.
|
|
771
|
-
|
|
775
|
+
_context4.next = 29;
|
|
776
|
+
break;
|
|
777
|
+
case 26:
|
|
778
|
+
_context4.prev = 26;
|
|
779
|
+
_context4.t1 = _context4["catch"](17);
|
|
772
780
|
_iterator.e(_context4.t1);
|
|
773
|
-
case
|
|
774
|
-
_context4.prev =
|
|
781
|
+
case 29:
|
|
782
|
+
_context4.prev = 29;
|
|
775
783
|
_iterator.f();
|
|
776
|
-
return _context4.finish(
|
|
777
|
-
case
|
|
784
|
+
return _context4.finish(29);
|
|
785
|
+
case 32:
|
|
778
786
|
if (!(0, _isEqual.default)(syncedBlocksToFlush, this.lastFlushedSyncedBlocks)) {
|
|
779
|
-
_context4.next =
|
|
787
|
+
_context4.next = 35;
|
|
780
788
|
break;
|
|
781
789
|
}
|
|
782
790
|
this.isCacheDirty = false; // Reset since we're considering this a successful no-op flush
|
|
783
791
|
return _context4.abrupt("return", true);
|
|
784
|
-
case
|
|
792
|
+
case 35:
|
|
785
793
|
// reset isCacheDirty early to prevent race condition
|
|
786
794
|
// There is a race condition where if a user makes changes (create/delete) to a reference sync block
|
|
787
795
|
// on a live page and the reference sync block is being saved while the user
|
|
@@ -789,9 +797,9 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
789
797
|
// exactly at a time when the updateReferenceData is being executed asynchronously.
|
|
790
798
|
this.isCacheDirty = false;
|
|
791
799
|
(_this$saveExperience = this.saveExperience) === null || _this$saveExperience === void 0 || _this$saveExperience.start();
|
|
792
|
-
_context4.next =
|
|
800
|
+
_context4.next = 39;
|
|
793
801
|
return this.dataProvider.updateReferenceData(blocks);
|
|
794
|
-
case
|
|
802
|
+
case 39:
|
|
795
803
|
updateResult = _context4.sent;
|
|
796
804
|
if (!updateResult.success) {
|
|
797
805
|
success = false;
|
|
@@ -800,11 +808,11 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
800
808
|
});
|
|
801
809
|
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 || _this$fireAnalyticsEv6.call(this, (0, _errorHandling.updateReferenceErrorPayload)(updateResult.error || 'Failed to update reference synced blocks on the document'));
|
|
802
810
|
}
|
|
803
|
-
_context4.next =
|
|
811
|
+
_context4.next = 49;
|
|
804
812
|
break;
|
|
805
|
-
case
|
|
806
|
-
_context4.prev =
|
|
807
|
-
_context4.t2 = _context4["catch"](
|
|
813
|
+
case 43:
|
|
814
|
+
_context4.prev = 43;
|
|
815
|
+
_context4.t2 = _context4["catch"](12);
|
|
808
816
|
success = false;
|
|
809
817
|
(0, _monitoring.logException)(_context4.t2, {
|
|
810
818
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
@@ -813,8 +821,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
813
821
|
reason: _context4.t2.message
|
|
814
822
|
});
|
|
815
823
|
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 || _this$fireAnalyticsEv7.call(this, (0, _errorHandling.updateReferenceErrorPayload)(_context4.t2.message));
|
|
816
|
-
case
|
|
817
|
-
_context4.prev =
|
|
824
|
+
case 49:
|
|
825
|
+
_context4.prev = 49;
|
|
818
826
|
if (!success) {
|
|
819
827
|
// set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
|
|
820
828
|
this.isCacheDirty = true;
|
|
@@ -836,14 +844,14 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
836
844
|
void _this7.flush();
|
|
837
845
|
}, 0);
|
|
838
846
|
}
|
|
839
|
-
return _context4.finish(
|
|
840
|
-
case
|
|
847
|
+
return _context4.finish(49);
|
|
848
|
+
case 54:
|
|
841
849
|
return _context4.abrupt("return", success);
|
|
842
|
-
case
|
|
850
|
+
case 55:
|
|
843
851
|
case "end":
|
|
844
852
|
return _context4.stop();
|
|
845
853
|
}
|
|
846
|
-
}, _callee3, this, [[
|
|
854
|
+
}, _callee3, this, [[12, 43, 49, 54], [17, 26, 29, 32]]);
|
|
847
855
|
}));
|
|
848
856
|
function flush() {
|
|
849
857
|
return _flush.apply(this, arguments);
|