PluginProbe
Gutenberg / 20.6.0
Gutenberg v20.6.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / hooks / index.js

index.js in Gutenberg 20.6.0, at build/hooks/index.js

622 lines 20.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ "use strict";
3 /******/ // The require scope
4 /******/ var __webpack_require__ = {};
5 /******/
6 /************************************************************************/
7 /******/ /* webpack/runtime/define property getters */
8 /******/ (() => {
9 /******/ // define getter functions for harmony exports
10 /******/ __webpack_require__.d = (exports, definition) => {
11 /******/ for(var key in definition) {
12 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
13 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
14 /******/ }
15 /******/ }
16 /******/ };
17 /******/ })();
18 /******/
19 /******/ /* webpack/runtime/hasOwnProperty shorthand */
20 /******/ (() => {
21 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
22 /******/ })();
23 /******/
24 /******/ /* webpack/runtime/make namespace object */
25 /******/ (() => {
26 /******/ // define __esModule on exports
27 /******/ __webpack_require__.r = (exports) => {
28 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
29 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
30 /******/ }
31 /******/ Object.defineProperty(exports, '__esModule', { value: true });
32 /******/ };
33 /******/ })();
34 /******/
35 /************************************************************************/
36 var __webpack_exports__ = {};
37 // ESM COMPAT FLAG
38 __webpack_require__.r(__webpack_exports__);
39
40 // EXPORTS
41 __webpack_require__.d(__webpack_exports__, {
42 actions: () => (/* binding */ actions),
43 addAction: () => (/* binding */ addAction),
44 addFilter: () => (/* binding */ addFilter),
45 applyFilters: () => (/* binding */ applyFilters),
46 applyFiltersAsync: () => (/* binding */ applyFiltersAsync),
47 createHooks: () => (/* reexport */ build_module_createHooks),
48 currentAction: () => (/* binding */ currentAction),
49 currentFilter: () => (/* binding */ currentFilter),
50 defaultHooks: () => (/* binding */ defaultHooks),
51 didAction: () => (/* binding */ didAction),
52 didFilter: () => (/* binding */ didFilter),
53 doAction: () => (/* binding */ doAction),
54 doActionAsync: () => (/* binding */ doActionAsync),
55 doingAction: () => (/* binding */ doingAction),
56 doingFilter: () => (/* binding */ doingFilter),
57 filters: () => (/* binding */ filters),
58 hasAction: () => (/* binding */ hasAction),
59 hasFilter: () => (/* binding */ hasFilter),
60 removeAction: () => (/* binding */ removeAction),
61 removeAllActions: () => (/* binding */ removeAllActions),
62 removeAllFilters: () => (/* binding */ removeAllFilters),
63 removeFilter: () => (/* binding */ removeFilter)
64 });
65
66 ;// ./packages/hooks/build-module/validateNamespace.js
67 /**
68 * Validate a namespace string.
69 *
70 * @param {string} namespace The namespace to validate - should take the form
71 * `vendor/plugin/function`.
72 *
73 * @return {boolean} Whether the namespace is valid.
74 */
75 function validateNamespace(namespace) {
76 if ('string' !== typeof namespace || '' === namespace) {
77 // eslint-disable-next-line no-console
78 console.error('The namespace must be a non-empty string.');
79 return false;
80 }
81 if (!/^[a-zA-Z][a-zA-Z0-9_.\-\/]*$/.test(namespace)) {
82 // eslint-disable-next-line no-console
83 console.error('The namespace can only contain numbers, letters, dashes, periods, underscores and slashes.');
84 return false;
85 }
86 return true;
87 }
88 /* harmony default export */ const build_module_validateNamespace = (validateNamespace);
89
90 ;// ./packages/hooks/build-module/validateHookName.js
91 /**
92 * Validate a hookName string.
93 *
94 * @param {string} hookName The hook name to validate. Should be a non empty string containing
95 * only numbers, letters, dashes, periods and underscores. Also,
96 * the hook name cannot begin with `__`.
97 *
98 * @return {boolean} Whether the hook name is valid.
99 */
100 function validateHookName(hookName) {
101 if ('string' !== typeof hookName || '' === hookName) {
102 // eslint-disable-next-line no-console
103 console.error('The hook name must be a non-empty string.');
104 return false;
105 }
106 if (/^__/.test(hookName)) {
107 // eslint-disable-next-line no-console
108 console.error('The hook name cannot begin with `__`.');
109 return false;
110 }
111 if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(hookName)) {
112 // eslint-disable-next-line no-console
113 console.error('The hook name can only contain numbers, letters, dashes, periods and underscores.');
114 return false;
115 }
116 return true;
117 }
118 /* harmony default export */ const build_module_validateHookName = (validateHookName);
119
120 ;// ./packages/hooks/build-module/createAddHook.js
121 /**
122 * Internal dependencies
123 */
124
125
126
127 /**
128 * @callback AddHook
129 *
130 * Adds the hook to the appropriate hooks container.
131 *
132 * @param {string} hookName Name of hook to add
133 * @param {string} namespace The unique namespace identifying the callback in the form `vendor/plugin/function`.
134 * @param {import('.').Callback} callback Function to call when the hook is run
135 * @param {number} [priority=10] Priority of this hook
136 */
137
138 /**
139 * Returns a function which, when invoked, will add a hook.
140 *
141 * @param {import('.').Hooks} hooks Hooks instance.
142 * @param {import('.').StoreKey} storeKey
143 *
144 * @return {AddHook} Function that adds a new hook.
145 */
146 function createAddHook(hooks, storeKey) {
147 return function addHook(hookName, namespace, callback, priority = 10) {
148 const hooksStore = hooks[storeKey];
149 if (!build_module_validateHookName(hookName)) {
150 return;
151 }
152 if (!build_module_validateNamespace(namespace)) {
153 return;
154 }
155 if ('function' !== typeof callback) {
156 // eslint-disable-next-line no-console
157 console.error('The hook callback must be a function.');
158 return;
159 }
160
161 // Validate numeric priority
162 if ('number' !== typeof priority) {
163 // eslint-disable-next-line no-console
164 console.error('If specified, the hook priority must be a number.');
165 return;
166 }
167 const handler = {
168 callback,
169 priority,
170 namespace
171 };
172 if (hooksStore[hookName]) {
173 // Find the correct insert index of the new hook.
174 const handlers = hooksStore[hookName].handlers;
175
176 /** @type {number} */
177 let i;
178 for (i = handlers.length; i > 0; i--) {
179 if (priority >= handlers[i - 1].priority) {
180 break;
181 }
182 }
183 if (i === handlers.length) {
184 // If append, operate via direct assignment.
185 handlers[i] = handler;
186 } else {
187 // Otherwise, insert before index via splice.
188 handlers.splice(i, 0, handler);
189 }
190
191 // We may also be currently executing this hook. If the callback
192 // we're adding would come after the current callback, there's no
193 // problem; otherwise we need to increase the execution index of
194 // any other runs by 1 to account for the added element.
195 hooksStore.__current.forEach(hookInfo => {
196 if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
197 hookInfo.currentIndex++;
198 }
199 });
200 } else {
201 // This is the first hook of its type.
202 hooksStore[hookName] = {
203 handlers: [handler],
204 runs: 0
205 };
206 }
207 if (hookName !== 'hookAdded') {
208 hooks.doAction('hookAdded', hookName, namespace, callback, priority);
209 }
210 };
211 }
212 /* harmony default export */ const build_module_createAddHook = (createAddHook);
213
214 ;// ./packages/hooks/build-module/createRemoveHook.js
215 /**
216 * Internal dependencies
217 */
218
219
220
221 /**
222 * @callback RemoveHook
223 * Removes the specified callback (or all callbacks) from the hook with a given hookName
224 * and namespace.
225 *
226 * @param {string} hookName The name of the hook to modify.
227 * @param {string} namespace The unique namespace identifying the callback in the
228 * form `vendor/plugin/function`.
229 *
230 * @return {number | undefined} The number of callbacks removed.
231 */
232
233 /**
234 * Returns a function which, when invoked, will remove a specified hook or all
235 * hooks by the given name.
236 *
237 * @param {import('.').Hooks} hooks Hooks instance.
238 * @param {import('.').StoreKey} storeKey
239 * @param {boolean} [removeAll=false] Whether to remove all callbacks for a hookName,
240 * without regard to namespace. Used to create
241 * `removeAll*` functions.
242 *
243 * @return {RemoveHook} Function that removes hooks.
244 */
245 function createRemoveHook(hooks, storeKey, removeAll = false) {
246 return function removeHook(hookName, namespace) {
247 const hooksStore = hooks[storeKey];
248 if (!build_module_validateHookName(hookName)) {
249 return;
250 }
251 if (!removeAll && !build_module_validateNamespace(namespace)) {
252 return;
253 }
254
255 // Bail if no hooks exist by this name.
256 if (!hooksStore[hookName]) {
257 return 0;
258 }
259 let handlersRemoved = 0;
260 if (removeAll) {
261 handlersRemoved = hooksStore[hookName].handlers.length;
262 hooksStore[hookName] = {
263 runs: hooksStore[hookName].runs,
264 handlers: []
265 };
266 } else {
267 // Try to find the specified callback to remove.
268 const handlers = hooksStore[hookName].handlers;
269 for (let i = handlers.length - 1; i >= 0; i--) {
270 if (handlers[i].namespace === namespace) {
271 handlers.splice(i, 1);
272 handlersRemoved++;
273 // This callback may also be part of a hook that is
274 // currently executing. If the callback we're removing
275 // comes after the current callback, there's no problem;
276 // otherwise we need to decrease the execution index of any
277 // other runs by 1 to account for the removed element.
278 hooksStore.__current.forEach(hookInfo => {
279 if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
280 hookInfo.currentIndex--;
281 }
282 });
283 }
284 }
285 }
286 if (hookName !== 'hookRemoved') {
287 hooks.doAction('hookRemoved', hookName, namespace);
288 }
289 return handlersRemoved;
290 };
291 }
292 /* harmony default export */ const build_module_createRemoveHook = (createRemoveHook);
293
294 ;// ./packages/hooks/build-module/createHasHook.js
295 /**
296 * @callback HasHook
297 *
298 * Returns whether any handlers are attached for the given hookName and optional namespace.
299 *
300 * @param {string} hookName The name of the hook to check for.
301 * @param {string} [namespace] Optional. The unique namespace identifying the callback
302 * in the form `vendor/plugin/function`.
303 *
304 * @return {boolean} Whether there are handlers that are attached to the given hook.
305 */
306 /**
307 * Returns a function which, when invoked, will return whether any handlers are
308 * attached to a particular hook.
309 *
310 * @param {import('.').Hooks} hooks Hooks instance.
311 * @param {import('.').StoreKey} storeKey
312 *
313 * @return {HasHook} Function that returns whether any handlers are
314 * attached to a particular hook and optional namespace.
315 */
316 function createHasHook(hooks, storeKey) {
317 return function hasHook(hookName, namespace) {
318 const hooksStore = hooks[storeKey];
319
320 // Use the namespace if provided.
321 if ('undefined' !== typeof namespace) {
322 return hookName in hooksStore && hooksStore[hookName].handlers.some(hook => hook.namespace === namespace);
323 }
324 return hookName in hooksStore;
325 };
326 }
327 /* harmony default export */ const build_module_createHasHook = (createHasHook);
328
329 ;// ./packages/hooks/build-module/createRunHook.js
330 /**
331 * Returns a function which, when invoked, will execute all callbacks
332 * registered to a hook of the specified type, optionally returning the final
333 * value of the call chain.
334 *
335 * @param {import('.').Hooks} hooks Hooks instance.
336 * @param {import('.').StoreKey} storeKey
337 * @param {boolean} returnFirstArg Whether each hook callback is expected to return its first argument.
338 * @param {boolean} async Whether the hook callback should be run asynchronously
339 *
340 * @return {(hookName:string, ...args: unknown[]) => undefined|unknown} Function that runs hook callbacks.
341 */
342 function createRunHook(hooks, storeKey, returnFirstArg, async) {
343 return function runHook(hookName, ...args) {
344 const hooksStore = hooks[storeKey];
345 if (!hooksStore[hookName]) {
346 hooksStore[hookName] = {
347 handlers: [],
348 runs: 0
349 };
350 }
351 hooksStore[hookName].runs++;
352 const handlers = hooksStore[hookName].handlers;
353
354 // The following code is stripped from production builds.
355 if (false) {}
356 if (!handlers || !handlers.length) {
357 return returnFirstArg ? args[0] : undefined;
358 }
359 const hookInfo = {
360 name: hookName,
361 currentIndex: 0
362 };
363 async function asyncRunner() {
364 try {
365 hooksStore.__current.add(hookInfo);
366 let result = returnFirstArg ? args[0] : undefined;
367 while (hookInfo.currentIndex < handlers.length) {
368 const handler = handlers[hookInfo.currentIndex];
369 result = await handler.callback.apply(null, args);
370 if (returnFirstArg) {
371 args[0] = result;
372 }
373 hookInfo.currentIndex++;
374 }
375 return returnFirstArg ? result : undefined;
376 } finally {
377 hooksStore.__current.delete(hookInfo);
378 }
379 }
380 function syncRunner() {
381 try {
382 hooksStore.__current.add(hookInfo);
383 let result = returnFirstArg ? args[0] : undefined;
384 while (hookInfo.currentIndex < handlers.length) {
385 const handler = handlers[hookInfo.currentIndex];
386 result = handler.callback.apply(null, args);
387 if (returnFirstArg) {
388 args[0] = result;
389 }
390 hookInfo.currentIndex++;
391 }
392 return returnFirstArg ? result : undefined;
393 } finally {
394 hooksStore.__current.delete(hookInfo);
395 }
396 }
397 return (async ? asyncRunner : syncRunner)();
398 };
399 }
400 /* harmony default export */ const build_module_createRunHook = (createRunHook);
401
402 ;// ./packages/hooks/build-module/createCurrentHook.js
403 /**
404 * Returns a function which, when invoked, will return the name of the
405 * currently running hook, or `null` if no hook of the given type is currently
406 * running.
407 *
408 * @param {import('.').Hooks} hooks Hooks instance.
409 * @param {import('.').StoreKey} storeKey
410 *
411 * @return {() => string | null} Function that returns the current hook name or null.
412 */
413 function createCurrentHook(hooks, storeKey) {
414 return function currentHook() {
415 var _currentArray$at$name;
416 const hooksStore = hooks[storeKey];
417 const currentArray = Array.from(hooksStore.__current);
418 return (_currentArray$at$name = currentArray.at(-1)?.name) !== null && _currentArray$at$name !== void 0 ? _currentArray$at$name : null;
419 };
420 }
421 /* harmony default export */ const build_module_createCurrentHook = (createCurrentHook);
422
423 ;// ./packages/hooks/build-module/createDoingHook.js
424 /**
425 * @callback DoingHook
426 * Returns whether a hook is currently being executed.
427 *
428 * @param {string} [hookName] The name of the hook to check for. If
429 * omitted, will check for any hook being executed.
430 *
431 * @return {boolean} Whether the hook is being executed.
432 */
433
434 /**
435 * Returns a function which, when invoked, will return whether a hook is
436 * currently being executed.
437 *
438 * @param {import('.').Hooks} hooks Hooks instance.
439 * @param {import('.').StoreKey} storeKey
440 *
441 * @return {DoingHook} Function that returns whether a hook is currently
442 * being executed.
443 */
444 function createDoingHook(hooks, storeKey) {
445 return function doingHook(hookName) {
446 const hooksStore = hooks[storeKey];
447
448 // If the hookName was not passed, check for any current hook.
449 if ('undefined' === typeof hookName) {
450 return hooksStore.__current.size > 0;
451 }
452
453 // Find if the `hookName` hook is in `__current`.
454 return Array.from(hooksStore.__current).some(hook => hook.name === hookName);
455 };
456 }
457 /* harmony default export */ const build_module_createDoingHook = (createDoingHook);
458
459 ;// ./packages/hooks/build-module/createDidHook.js
460 /**
461 * Internal dependencies
462 */
463
464
465 /**
466 * @callback DidHook
467 *
468 * Returns the number of times an action has been fired.
469 *
470 * @param {string} hookName The hook name to check.
471 *
472 * @return {number | undefined} The number of times the hook has run.
473 */
474
475 /**
476 * Returns a function which, when invoked, will return the number of times a
477 * hook has been called.
478 *
479 * @param {import('.').Hooks} hooks Hooks instance.
480 * @param {import('.').StoreKey} storeKey
481 *
482 * @return {DidHook} Function that returns a hook's call count.
483 */
484 function createDidHook(hooks, storeKey) {
485 return function didHook(hookName) {
486 const hooksStore = hooks[storeKey];
487 if (!build_module_validateHookName(hookName)) {
488 return;
489 }
490 return hooksStore[hookName] && hooksStore[hookName].runs ? hooksStore[hookName].runs : 0;
491 };
492 }
493 /* harmony default export */ const build_module_createDidHook = (createDidHook);
494
495 ;// ./packages/hooks/build-module/createHooks.js
496 /**
497 * Internal dependencies
498 */
499
500
501
502
503
504
505
506
507 /**
508 * Internal class for constructing hooks. Use `createHooks()` function
509 *
510 * Note, it is necessary to expose this class to make its type public.
511 *
512 * @private
513 */
514 class _Hooks {
515 constructor() {
516 /** @type {import('.').Store} actions */
517 this.actions = Object.create(null);
518 this.actions.__current = new Set();
519
520 /** @type {import('.').Store} filters */
521 this.filters = Object.create(null);
522 this.filters.__current = new Set();
523 this.addAction = build_module_createAddHook(this, 'actions');
524 this.addFilter = build_module_createAddHook(this, 'filters');
525 this.removeAction = build_module_createRemoveHook(this, 'actions');
526 this.removeFilter = build_module_createRemoveHook(this, 'filters');
527 this.hasAction = build_module_createHasHook(this, 'actions');
528 this.hasFilter = build_module_createHasHook(this, 'filters');
529 this.removeAllActions = build_module_createRemoveHook(this, 'actions', true);
530 this.removeAllFilters = build_module_createRemoveHook(this, 'filters', true);
531 this.doAction = build_module_createRunHook(this, 'actions', false, false);
532 this.doActionAsync = build_module_createRunHook(this, 'actions', false, true);
533 this.applyFilters = build_module_createRunHook(this, 'filters', true, false);
534 this.applyFiltersAsync = build_module_createRunHook(this, 'filters', true, true);
535 this.currentAction = build_module_createCurrentHook(this, 'actions');
536 this.currentFilter = build_module_createCurrentHook(this, 'filters');
537 this.doingAction = build_module_createDoingHook(this, 'actions');
538 this.doingFilter = build_module_createDoingHook(this, 'filters');
539 this.didAction = build_module_createDidHook(this, 'actions');
540 this.didFilter = build_module_createDidHook(this, 'filters');
541 }
542 }
543
544 /** @typedef {_Hooks} Hooks */
545
546 /**
547 * Returns an instance of the hooks object.
548 *
549 * @return {Hooks} A Hooks instance.
550 */
551 function createHooks() {
552 return new _Hooks();
553 }
554 /* harmony default export */ const build_module_createHooks = (createHooks);
555
556 ;// ./packages/hooks/build-module/index.js
557 /**
558 * Internal dependencies
559 */
560
561
562 /** @typedef {(...args: any[])=>any} Callback */
563
564 /**
565 * @typedef Handler
566 * @property {Callback} callback The callback
567 * @property {string} namespace The namespace
568 * @property {number} priority The namespace
569 */
570
571 /**
572 * @typedef Hook
573 * @property {Handler[]} handlers Array of handlers
574 * @property {number} runs Run counter
575 */
576
577 /**
578 * @typedef Current
579 * @property {string} name Hook name
580 * @property {number} currentIndex The index
581 */
582
583 /**
584 * @typedef {Record<string, Hook> & {__current: Set<Current>}} Store
585 */
586
587 /**
588 * @typedef {'actions' | 'filters'} StoreKey
589 */
590
591 /**
592 * @typedef {import('./createHooks').Hooks} Hooks
593 */
594
595 const defaultHooks = build_module_createHooks();
596 const {
597 addAction,
598 addFilter,
599 removeAction,
600 removeFilter,
601 hasAction,
602 hasFilter,
603 removeAllActions,
604 removeAllFilters,
605 doAction,
606 doActionAsync,
607 applyFilters,
608 applyFiltersAsync,
609 currentAction,
610 currentFilter,
611 doingAction,
612 doingFilter,
613 didAction,
614 didFilter,
615 actions,
616 filters
617 } = defaultHooks;
618
619
620 (window.wp = window.wp || {}).hooks = __webpack_exports__;
621 /******/ })()
622 ;