glass-easel 0.2.0 → 0.3.0

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.
Files changed (197) hide show
  1. package/.eslintignore +4 -0
  2. package/dist/glass_easel.all.js +2 -2
  3. package/dist/glass_easel.all.js.map +1 -1
  4. package/dist/glass_easel.d.ts +2546 -0
  5. package/dist/glass_easel.domlike.global.js +2 -2
  6. package/dist/glass_easel.domlike.global.js.map +1 -1
  7. package/guide/zh_CN/appendix/backend_protocol.md +164 -74
  8. package/jest.unit.config.js +7 -4
  9. package/package.json +7 -5
  10. package/rollup.config.ts +101 -0
  11. package/src/backend/backend_protocol.ts +26 -345
  12. package/src/backend/composed_backend_protocol.ts +10 -264
  13. package/src/backend/current_window_backend_context.ts +478 -0
  14. package/src/backend/domlike_backend_protocol.ts +9 -498
  15. package/src/backend/empty_backend.ts +265 -0
  16. package/src/backend/empty_composed_backend.ts +245 -0
  17. package/src/backend/index.ts +18 -0
  18. package/src/backend/suggested_backend_protocol.ts +62 -11
  19. package/src/behavior.ts +131 -442
  20. package/src/class_list.ts +328 -222
  21. package/src/component.ts +349 -184
  22. package/src/component_params.ts +54 -25
  23. package/src/component_space.ts +36 -15
  24. package/src/data_path.ts +22 -34
  25. package/src/data_proxy.ts +334 -27
  26. package/src/devtool.ts +89 -0
  27. package/src/element.ts +667 -285
  28. package/src/element_iterator.ts +9 -4
  29. package/src/event.ts +39 -20
  30. package/src/external_shadow_tree.ts +2 -2
  31. package/src/func_arr.ts +55 -101
  32. package/src/global_options.ts +18 -42
  33. package/src/index.ts +72 -73
  34. package/src/mutation_observer.ts +10 -7
  35. package/src/native_node.ts +79 -35
  36. package/src/node.ts +23 -30
  37. package/src/relation.ts +101 -12
  38. package/src/render.ts +5 -3
  39. package/src/selector.ts +9 -7
  40. package/src/shadow_root.ts +96 -240
  41. package/src/template_engine.ts +10 -7
  42. package/src/text_node.ts +43 -19
  43. package/src/tmpl/index.ts +38 -30
  44. package/src/tmpl/native_rendering.ts +14 -21
  45. package/src/tmpl/proc_gen_wrapper.ts +189 -151
  46. package/src/tmpl/proc_gen_wrapper_dom.ts +10 -8
  47. package/src/tmpl/range_list_diff.ts +30 -9
  48. package/src/trait_behaviors.ts +1 -1
  49. package/src/type_symbol.ts +36 -0
  50. package/src/virtual_node.ts +26 -13
  51. package/src/warning.ts +119 -0
  52. package/tests/base/composed_backend.ts +143 -142
  53. package/tests/base/env.ts +76 -3
  54. package/tests/base/match.ts +24 -22
  55. package/tests/base/shadow_backend.ts +917 -0
  56. package/tests/core/backend.test.ts +53 -1
  57. package/tests/core/behavior.test.ts +1 -1
  58. package/tests/core/data_update.test.ts +135 -0
  59. package/tests/core/misc.test.ts +91 -21
  60. package/tests/core/placeholder.test.ts +66 -25
  61. package/tests/core/slot.test.ts +161 -23
  62. package/tests/legacy/component.test.js +152 -78
  63. package/tests/legacy/data_path.test.js +19 -19
  64. package/tests/legacy/data_proxy.test.js +14 -7
  65. package/tests/legacy/external.test.js +8 -8
  66. package/tests/legacy/mutation_observer.test.js +7 -5
  67. package/tests/legacy/slot.test.js +2 -3
  68. package/tests/legacy/virtual.test.js +258 -25
  69. package/tests/tmpl/binding_map.test.ts +201 -195
  70. package/tests/tmpl/event.test.ts +138 -23
  71. package/tests/tmpl/expression.test.ts +15 -15
  72. package/tests/tmpl/lvalue.test.ts +101 -0
  73. package/tests/tmpl/structure.test.ts +486 -43
  74. package/tests/types/chaining.test.ts +27 -30
  75. package/tests/types/createElement.test.ts +5 -4
  76. package/tests/types/definition.test.ts +11 -14
  77. package/tsconfig.json +1 -3
  78. package/dist/glass_easel.all.d.ts +0 -1
  79. package/dist/glass_easel.domlike.global.d.ts +0 -1
  80. package/dist/index.d.ts +0 -1
  81. package/dist/index.js +0 -1
  82. package/dist/types/src/backend/backend_protocol.d.ts +0 -141
  83. package/dist/types/src/backend/backend_protocol.d.ts.map +0 -1
  84. package/dist/types/src/backend/composed_backend_protocol.d.ts +0 -102
  85. package/dist/types/src/backend/composed_backend_protocol.d.ts.map +0 -1
  86. package/dist/types/src/backend/domlike_backend_protocol.d.ts +0 -100
  87. package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +0 -1
  88. package/dist/types/src/backend/mode.d.ts +0 -65
  89. package/dist/types/src/backend/mode.d.ts.map +0 -1
  90. package/dist/types/src/backend/suggested_backend_protocol.d.ts +0 -30
  91. package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +0 -1
  92. package/dist/types/src/behavior.d.ts +0 -434
  93. package/dist/types/src/behavior.d.ts.map +0 -1
  94. package/dist/types/src/class_list.d.ts +0 -83
  95. package/dist/types/src/class_list.d.ts.map +0 -1
  96. package/dist/types/src/component.d.ts +0 -325
  97. package/dist/types/src/component.d.ts.map +0 -1
  98. package/dist/types/src/component_params.d.ts +0 -236
  99. package/dist/types/src/component_params.d.ts.map +0 -1
  100. package/dist/types/src/component_space.d.ts +0 -211
  101. package/dist/types/src/component_space.d.ts.map +0 -1
  102. package/dist/types/src/data_path.d.ts +0 -5
  103. package/dist/types/src/data_path.d.ts.map +0 -1
  104. package/dist/types/src/data_proxy.d.ts +0 -107
  105. package/dist/types/src/data_proxy.d.ts.map +0 -1
  106. package/dist/types/src/data_utils.d.ts +0 -3
  107. package/dist/types/src/data_utils.d.ts.map +0 -1
  108. package/dist/types/src/element.d.ts +0 -365
  109. package/dist/types/src/element.d.ts.map +0 -1
  110. package/dist/types/src/element_iterator.d.ts +0 -43
  111. package/dist/types/src/element_iterator.d.ts.map +0 -1
  112. package/dist/types/src/event.d.ts +0 -105
  113. package/dist/types/src/event.d.ts.map +0 -1
  114. package/dist/types/src/external_shadow_tree.d.ts +0 -20
  115. package/dist/types/src/external_shadow_tree.d.ts.map +0 -1
  116. package/dist/types/src/func_arr.d.ts +0 -39
  117. package/dist/types/src/func_arr.d.ts.map +0 -1
  118. package/dist/types/src/global_options.d.ts +0 -120
  119. package/dist/types/src/global_options.d.ts.map +0 -1
  120. package/dist/types/src/index.d.ts +0 -43
  121. package/dist/types/src/index.d.ts.map +0 -1
  122. package/dist/types/src/mutation_observer.d.ts +0 -79
  123. package/dist/types/src/mutation_observer.d.ts.map +0 -1
  124. package/dist/types/src/native_node.d.ts +0 -11
  125. package/dist/types/src/native_node.d.ts.map +0 -1
  126. package/dist/types/src/node.d.ts +0 -48
  127. package/dist/types/src/node.d.ts.map +0 -1
  128. package/dist/types/src/relation.d.ts +0 -46
  129. package/dist/types/src/relation.d.ts.map +0 -1
  130. package/dist/types/src/render.d.ts +0 -3
  131. package/dist/types/src/render.d.ts.map +0 -1
  132. package/dist/types/src/selector.d.ts +0 -32
  133. package/dist/types/src/selector.d.ts.map +0 -1
  134. package/dist/types/src/shadow_root.d.ts +0 -174
  135. package/dist/types/src/shadow_root.d.ts.map +0 -1
  136. package/dist/types/src/template_engine.d.ts +0 -56
  137. package/dist/types/src/template_engine.d.ts.map +0 -1
  138. package/dist/types/src/text_node.d.ts +0 -44
  139. package/dist/types/src/text_node.d.ts.map +0 -1
  140. package/dist/types/src/tmpl/index.d.ts +0 -19
  141. package/dist/types/src/tmpl/index.d.ts.map +0 -1
  142. package/dist/types/src/tmpl/native_rendering.d.ts +0 -45
  143. package/dist/types/src/tmpl/native_rendering.d.ts.map +0 -1
  144. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +0 -89
  145. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +0 -1
  146. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +0 -50
  147. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +0 -1
  148. package/dist/types/src/tmpl/range_list_diff.d.ts +0 -19
  149. package/dist/types/src/tmpl/range_list_diff.d.ts.map +0 -1
  150. package/dist/types/src/trait_behaviors.d.ts +0 -38
  151. package/dist/types/src/trait_behaviors.d.ts.map +0 -1
  152. package/dist/types/src/virtual_node.d.ts +0 -10
  153. package/dist/types/src/virtual_node.d.ts.map +0 -1
  154. package/dist/types/tests/backend/domlike.test.d.ts +0 -2
  155. package/dist/types/tests/backend/domlike.test.d.ts.map +0 -1
  156. package/dist/types/tests/base/composed_backend.d.ts +0 -123
  157. package/dist/types/tests/base/composed_backend.d.ts.map +0 -1
  158. package/dist/types/tests/base/env.d.ts +0 -30
  159. package/dist/types/tests/base/env.d.ts.map +0 -1
  160. package/dist/types/tests/base/match.d.ts +0 -9
  161. package/dist/types/tests/base/match.d.ts.map +0 -1
  162. package/dist/types/tests/core/backend.test.d.ts +0 -2
  163. package/dist/types/tests/core/backend.test.d.ts.map +0 -1
  164. package/dist/types/tests/core/behavior.test.d.ts +0 -2
  165. package/dist/types/tests/core/behavior.test.d.ts.map +0 -1
  166. package/dist/types/tests/core/component_space.test.d.ts +0 -2
  167. package/dist/types/tests/core/component_space.test.d.ts.map +0 -1
  168. package/dist/types/tests/core/data_update.test.d.ts +0 -2
  169. package/dist/types/tests/core/data_update.test.d.ts.map +0 -1
  170. package/dist/types/tests/core/misc.test.d.ts +0 -2
  171. package/dist/types/tests/core/misc.test.d.ts.map +0 -1
  172. package/dist/types/tests/core/placeholder.test.d.ts +0 -2
  173. package/dist/types/tests/core/placeholder.test.d.ts.map +0 -1
  174. package/dist/types/tests/core/slot.test.d.ts +0 -2
  175. package/dist/types/tests/core/slot.test.d.ts.map +0 -1
  176. package/dist/types/tests/core/trait_behaviors.test.d.ts +0 -2
  177. package/dist/types/tests/core/trait_behaviors.test.d.ts.map +0 -1
  178. package/dist/types/tests/tmpl/binding_map.test.d.ts +0 -2
  179. package/dist/types/tests/tmpl/binding_map.test.d.ts.map +0 -1
  180. package/dist/types/tests/tmpl/event.test.d.ts +0 -2
  181. package/dist/types/tests/tmpl/event.test.d.ts.map +0 -1
  182. package/dist/types/tests/tmpl/expression.test.d.ts +0 -2
  183. package/dist/types/tests/tmpl/expression.test.d.ts.map +0 -1
  184. package/dist/types/tests/tmpl/lvalue.test.d.ts +0 -2
  185. package/dist/types/tests/tmpl/lvalue.test.d.ts.map +0 -1
  186. package/dist/types/tests/tmpl/native_rendering.test.d.ts +0 -2
  187. package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +0 -1
  188. package/dist/types/tests/tmpl/structure.test.d.ts +0 -2
  189. package/dist/types/tests/tmpl/structure.test.d.ts.map +0 -1
  190. package/dist/types/tests/types/chaining.test.d.ts +0 -2
  191. package/dist/types/tests/types/chaining.test.d.ts.map +0 -1
  192. package/dist/types/tests/types/createElement.test.d.ts +0 -2
  193. package/dist/types/tests/types/createElement.test.d.ts.map +0 -1
  194. package/dist/types/tests/types/definition.test.d.ts +0 -2
  195. package/dist/types/tests/types/definition.test.d.ts.map +0 -1
  196. package/webpack.config.js +0 -275
  197. /package/src/backend/{mode.ts → shared.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { Element } from './element'
2
- import { TextNode } from './text_node'
3
- import { Node } from './node'
2
+ import { type Node } from './node'
3
+ import { isElement, isTextNode } from './type_symbol'
4
4
 
5
5
  /** The iterator direction and order */
6
6
  export const enum ElementIteratorType {
@@ -24,10 +24,15 @@ export const enum ElementIteratorType {
24
24
  * This iterator is convenient but seems a little slower.
25
25
  */
26
26
  export class ElementIterator {
27
+ /* @internal */
27
28
  private _$node: Node
29
+ /* @internal */
28
30
  private _$nodeTypeLimit: unknown
31
+ /* @internal */
29
32
  private _$composed: boolean
33
+ /* @internal */
30
34
  private _$isAncestor: boolean
35
+ /* @internal */
31
36
  private _$rootFirst: boolean
32
37
 
33
38
  /**
@@ -41,7 +46,7 @@ export class ElementIterator {
41
46
  * Specify `Component` will only return components.
42
47
  */
43
48
  constructor(node: Node, type: ElementIteratorType, nodeTypeLimit: unknown = Element) {
44
- if (!(node instanceof Element) && !(node instanceof TextNode)) {
49
+ if (!isElement(node) && !isTextNode(node)) {
45
50
  throw new Error('Element iterators can only be used in elements or text nodes')
46
51
  }
47
52
  this._$node = node
@@ -110,7 +115,7 @@ export class ElementIterator {
110
115
  if (f(node) === false) return false
111
116
  }
112
117
  }
113
- if (node instanceof Element) {
118
+ if (isElement(node)) {
114
119
  let interrupted = false
115
120
  const childFn = (child: Node) => {
116
121
  if (rec(child) === false) {
package/src/event.ts CHANGED
@@ -1,12 +1,11 @@
1
+ import { type GeneralBackendElement } from './backend'
2
+ import { type GeneralComponent } from './component'
3
+ import { addTimelineEvent, performanceMeasureEnd, performanceMeasureStart } from './devtool'
4
+ import { type Element } from './element'
5
+ import { type ExternalShadowRoot } from './external_shadow_tree'
1
6
  import { FuncArrWithMeta } from './func_arr'
2
- import {
3
- Element,
4
- Component,
5
- GeneralComponent,
6
- ShadowRoot,
7
- GeneralBackendElement,
8
- ExternalShadowRoot,
9
- } from '.'
7
+ import { ENV } from './global_options'
8
+ import { isComponent, isShadowRoot } from './type_symbol'
10
9
 
11
10
  /**
12
11
  * Options for an event
@@ -17,6 +16,7 @@ export type EventOptions = {
17
16
  composed?: boolean
18
17
  capturePhase?: boolean
19
18
  extraFields?: { [key: string]: unknown }
19
+ handleListenerReturn?: (ret: unknown) => boolean | void
20
20
  }
21
21
 
22
22
  /**
@@ -116,7 +116,7 @@ export class EventTarget<TEvents extends { [type: string]: unknown }> {
116
116
  efa = listeners[name] = {
117
117
  mutCount: 0,
118
118
  finalCount: 0,
119
- funcArr: new FuncArrWithMeta(),
119
+ funcArr: new FuncArrWithMeta('listener'),
120
120
  }
121
121
  }
122
122
  efa.funcArr.add(func, mutLevel)
@@ -177,6 +177,8 @@ export class Event<TDetail> {
177
177
  bubbles: boolean
178
178
  composed: boolean
179
179
  /** @internal */
180
+ private _$eventName: string
181
+ /** @internal */
180
182
  private _$capturePhase: boolean
181
183
  /** @internal */
182
184
  private _$originalEvent: unknown
@@ -188,10 +190,12 @@ export class Event<TDetail> {
188
190
  mutated: boolean
189
191
  noDefault: boolean
190
192
  }
193
+ /** @internal */
194
+ private _$handleListenerReturn: ((ret: unknown) => boolean | void) | undefined
191
195
 
192
196
  constructor(name: string, detail: TDetail, options: EventOptions = {}) {
193
197
  const ts = getCurrentTimeStamp()
194
- this.type = name
198
+ this._$eventName = this.type = name
195
199
  this.timeStamp = ts
196
200
  this.detail = detail
197
201
  this.bubbles = options.bubbles || false
@@ -204,6 +208,7 @@ export class Event<TDetail> {
204
208
  }
205
209
  this._$originalEvent = options.originalEvent
206
210
  this._$dispatched = false
211
+ this._$handleListenerReturn = options.handleListenerReturn
207
212
  if (options.extraFields) {
208
213
  Object.assign(this, options.extraFields)
209
214
  }
@@ -226,6 +231,10 @@ export class Event<TDetail> {
226
231
  return ret
227
232
  }
228
233
 
234
+ getEventName(): string {
235
+ return this._$eventName
236
+ }
237
+
229
238
  getOriginalEvent(): unknown {
230
239
  return this._$originalEvent
231
240
  }
@@ -254,13 +263,17 @@ export class Event<TDetail> {
254
263
  return this._$eventBubblingControl.mutated
255
264
  }
256
265
 
266
+ listenerReturnHandler() {
267
+ return this._$handleListenerReturn
268
+ }
269
+
257
270
  callListener(
258
271
  currentTarget: Element,
259
272
  mark: Record<string, unknown> | null,
260
273
  target: Element,
261
274
  isCapture: boolean,
262
275
  ) {
263
- const evName = this.type
276
+ const evName = this._$eventName
264
277
 
265
278
  const eventTarget = currentTarget._$eventTarget
266
279
  if (!eventTarget) return
@@ -270,18 +283,18 @@ export class Event<TDetail> {
270
283
  if (!efa) return
271
284
  const skipMut = this.mutatedMarked()
272
285
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
273
- const targetCaller = target instanceof Component ? target.getMethodCaller() || target : target
286
+ const targetCaller = isComponent(target) ? target.getMethodCaller() || target : target
274
287
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
275
- const currentTargetCaller =
276
- currentTarget instanceof Component
277
- ? currentTarget.getMethodCaller() || currentTarget
278
- : currentTarget
288
+ const currentTargetCaller = isComponent(currentTarget)
289
+ ? currentTarget.getMethodCaller() || currentTarget
290
+ : currentTarget
279
291
  const ev = this.wrapShadowedEvent(targetCaller, mark, currentTargetCaller)
280
292
  const ret = efa.funcArr.call(
281
293
  currentTargetCaller,
282
294
  [ev],
283
295
  (mulLevel) => !skipMut || mulLevel !== MutLevel.Mut,
284
- target instanceof Component ? (target as GeneralComponent) : undefined,
296
+ isComponent(target) ? target : undefined,
297
+ this._$handleListenerReturn,
285
298
  )
286
299
  if (ret === false || efa.finalCount > 0) {
287
300
  ev.stopPropagation()
@@ -295,6 +308,10 @@ export class Event<TDetail> {
295
308
  if (this._$dispatched) {
296
309
  throw new Error('Event cannot be dispatched twice')
297
310
  }
311
+ if (ENV.DEV) {
312
+ addTimelineEvent(this._$eventName, { event: this })
313
+ performanceMeasureStart('event.dispatch')
314
+ }
298
315
  this._$dispatched = true
299
316
  const crossShadow = this.composed
300
317
  const bubbles = this.bubbles
@@ -312,7 +329,7 @@ export class Event<TDetail> {
312
329
  if (f(currentTarget, target, mark) === false) return null
313
330
  let next
314
331
  if (crossShadow) {
315
- if (currentTarget instanceof ShadowRoot) return currentTarget.getHostNode()
332
+ if (isShadowRoot(currentTarget)) return currentTarget.getHostNode()
316
333
  if (currentTarget.containingSlot === null) return null
317
334
  if (currentTarget.containingSlot) {
318
335
  next = recShadow(currentTarget.containingSlot)
@@ -354,7 +371,7 @@ export class Event<TDetail> {
354
371
 
355
372
  // bubble phase in external component
356
373
  if (!eventBubblingControl.stopped && externalTarget) {
357
- if (target instanceof Component && target._$external) {
374
+ if (isComponent(target) && target._$external) {
358
375
  ;(target.shadowRoot as ExternalShadowRoot).handleEvent(externalTarget, this)
359
376
  }
360
377
  }
@@ -363,7 +380,7 @@ export class Event<TDetail> {
363
380
  if (!eventBubblingControl.stopped && !inExternalOnly) {
364
381
  let atTarget = true
365
382
  forEachBubblePath(target, (currentTarget, target, mark) => {
366
- if (!atTarget && currentTarget instanceof Component && currentTarget._$external) {
383
+ if (!atTarget && isComponent(currentTarget) && currentTarget._$external) {
367
384
  const sr = currentTarget.shadowRoot as ExternalShadowRoot
368
385
  sr.handleEvent(sr.slot, this)
369
386
  }
@@ -374,6 +391,8 @@ export class Event<TDetail> {
374
391
  return bubbles && !eventBubblingControl.stopped
375
392
  })
376
393
  }
394
+
395
+ if (ENV.DEV) performanceMeasureEnd()
377
396
  }
378
397
 
379
398
  static dispatchEvent<TDetail>(target: Element, event: Event<TDetail>) {
@@ -1,5 +1,5 @@
1
- import { Event, ShadowedEvent } from './event'
2
- import { GeneralBackendElement } from './node'
1
+ import { type Event, type ShadowedEvent } from './event'
2
+ import { type GeneralBackendElement } from './backend'
3
3
 
4
4
  /**
5
5
  * An external shadow root
package/src/func_arr.ts CHANGED
@@ -1,31 +1,18 @@
1
- import { Component, GeneralComponent } from '.'
2
- import { globalOptions } from './global_options'
1
+ import { type AnyComponent, type GeneralComponent } from './component'
2
+ import { performanceMeasureEnd, performanceMeasureStart } from './devtool'
3
+ import { ENV } from './global_options'
4
+ import { type Node } from './node'
3
5
 
4
6
  export type GeneralFuncType = (this: any, ...args: any[]) => any
5
7
 
6
- type ErrorInfo = {
7
- message: string
8
- type: string
9
- element: unknown
10
- method: unknown
11
- args: unknown[]
12
- }
13
-
14
- function dispatchError(err: unknown, info: ErrorInfo, avoidErrorHandler?: boolean) {
15
- if (!avoidErrorHandler && errorFuncArr.call(err as any, [err, info]) === false) return
16
- if (globalOptions.throwGlobalError) {
17
- throw err
18
- } else {
19
- // eslint-disable-next-line no-console
20
- console.error(err instanceof Error ? `${err.message}\n${err.stack || ''}` : String(err))
21
- }
22
- }
23
-
24
8
  export class FuncArr<F extends GeneralFuncType> {
25
9
  empty = true
26
- private _$type = ''
10
+ private _$type: string
27
11
  private _$arr: F[] | null = null
28
- _$avoidErrorHandler = false
12
+
13
+ constructor(type: string) {
14
+ this._$type = type
15
+ }
29
16
 
30
17
  add(func: F) {
31
18
  if (!this._$arr) this._$arr = [func]
@@ -52,93 +39,32 @@ export class FuncArr<F extends GeneralFuncType> {
52
39
  return ret
53
40
  }
54
41
 
55
- call(caller: ThisType<F>, args: Parameters<F>, relatedComponent?: GeneralComponent): boolean {
42
+ call(
43
+ caller: ThisParameterType<F>,
44
+ args: Parameters<F>,
45
+ relatedComponent?: AnyComponent,
46
+ ): boolean {
56
47
  const arr = this._$arr
57
48
  let ret = true
58
49
  if (arr) {
59
50
  for (let i = 0; i < arr.length; i += 1) {
60
- const r = safeCallback(
61
- this._$type,
62
- arr[i]!,
63
- caller,
64
- args,
65
- relatedComponent,
66
- this._$avoidErrorHandler,
67
- )
51
+ const r = safeCallback<F>(this._$type, arr[i]!, caller, args, relatedComponent)
68
52
  if (r === false) ret = false
69
53
  }
70
54
  }
71
55
  return ret
72
56
  }
73
-
74
- static safeCallback<F extends GeneralFuncType>(
75
- this: void,
76
- type: string,
77
- method: F,
78
- caller: ThisType<F>,
79
- args: Parameters<F>,
80
- relatedComponent?: GeneralComponent,
81
- avoidErrorHandler = false,
82
- ): ReturnType<F> | undefined {
83
- try {
84
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
85
- return method.apply(caller, args)
86
- } catch (e) {
87
- let msg = `[Error] [Component] ${type || 'Error Listener'} Error @ `
88
- if (caller instanceof Component) msg += caller.is
89
- msg += `#${method.name || '(anonymous)'}`
90
- if (relatedComponent) {
91
- relatedComponent.triggerLifetime('error', [e])
92
- }
93
- dispatchError(
94
- e,
95
- {
96
- message: msg,
97
- type,
98
- element: caller,
99
- method,
100
- args,
101
- },
102
- avoidErrorHandler,
103
- )
104
- return undefined
105
- }
106
- }
107
-
108
- static addGlobalErrorListener(this: void, func: (err: Error, info: ErrorInfo) => boolean) {
109
- errorFuncArr.add(func)
110
- }
111
-
112
- static removeGlobalErrorListener(this: void, func: (err: Error, info: ErrorInfo) => boolean) {
113
- errorFuncArr.remove(func)
114
- }
115
-
116
- static addGlobalWarningListener(this: void, func: (msg: string) => void) {
117
- warningFuncArr.add(func)
118
- }
119
-
120
- static removeGlobalWarningListener(this: void, func: (msg: string) => void) {
121
- warningFuncArr.remove(func)
122
- }
123
- }
124
-
125
- export function triggerWarning(msg: string) {
126
- const message = `[Warning] [Component] ${msg}`
127
- if (warningFuncArr.call(message, [message])) {
128
- // eslint-disable-next-line no-console
129
- console.warn(message)
130
- }
131
57
  }
132
58
 
133
- const errorFuncArr = new FuncArr()
134
- errorFuncArr._$avoidErrorHandler = true
135
- const warningFuncArr = new FuncArr()
136
-
137
59
  export class FuncArrWithMeta<F extends GeneralFuncType, T> {
138
60
  empty = true
139
- private _$type = ''
61
+ private _$type: string
140
62
  private _$arr: { f: F; data: T }[] | null = null
141
63
 
64
+ constructor(type: string) {
65
+ this._$type = type
66
+ }
67
+
142
68
  add(func: F, data: T) {
143
69
  const item = { f: func, data }
144
70
  if (!this._$arr) this._$arr = [item]
@@ -167,10 +93,11 @@ export class FuncArrWithMeta<F extends GeneralFuncType, T> {
167
93
  }
168
94
 
169
95
  call(
170
- caller: ThisType<F>,
96
+ caller: ThisParameterType<F>,
171
97
  args: Parameters<F>,
172
98
  retainFn: (data: T) => boolean,
173
99
  relatedComponent?: GeneralComponent,
100
+ handleReturn?: (ret: unknown) => boolean | void,
174
101
  ): boolean {
175
102
  const arr = this._$arr
176
103
  let ret = true
@@ -178,7 +105,8 @@ export class FuncArrWithMeta<F extends GeneralFuncType, T> {
178
105
  for (let i = 0; i < arr.length; i += 1) {
179
106
  const { f, data } = arr[i]!
180
107
  if (!retainFn(data)) continue
181
- const r = FuncArr.safeCallback(this._$type, f, caller, args, relatedComponent)
108
+ const rawReturn = safeCallback(this._$type, f, caller, args, relatedComponent)
109
+ const r = handleReturn ? handleReturn(rawReturn) : rawReturn
182
110
  if (r === false) ret = false
183
111
  }
184
112
  }
@@ -186,8 +114,34 @@ export class FuncArrWithMeta<F extends GeneralFuncType, T> {
186
114
  }
187
115
  }
188
116
 
189
- export const safeCallback = FuncArr.safeCallback
190
- export const addGlobalErrorListener = FuncArr.addGlobalErrorListener
191
- export const removeGlobalErrorListener = FuncArr.removeGlobalErrorListener
192
- export const addGlobalWarningListener = FuncArr.addGlobalWarningListener
193
- export const removeGlobalWarningListener = FuncArr.removeGlobalWarningListener
117
+ let dispatchError: (
118
+ err: unknown,
119
+ method?: string,
120
+ relatedComponent?: AnyComponent | string,
121
+ element?: Node,
122
+ ) => void = () => {}
123
+
124
+ export function _setErrorDispatcher(dispatcher: typeof dispatchError) {
125
+ dispatchError = dispatcher
126
+ }
127
+
128
+ export function safeCallback<F extends GeneralFuncType>(
129
+ this: void,
130
+ type: string,
131
+ method: F,
132
+ caller: ThisParameterType<F>,
133
+ args: Parameters<F>,
134
+ relatedComponent?: AnyComponent,
135
+ ): ReturnType<F> | undefined {
136
+ try {
137
+ if (ENV.DEV)
138
+ performanceMeasureStart(`${type}.${method.name || '(anonymous)'}`, relatedComponent, { args })
139
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
140
+ return method.apply(caller, args)
141
+ } catch (e) {
142
+ dispatchError(e, `${type || 'Listener'} ${method.name || '(anonymous)'}`, relatedComponent)
143
+ return undefined
144
+ } finally {
145
+ if (ENV.DEV) performanceMeasureEnd()
146
+ }
147
+ }
@@ -1,13 +1,13 @@
1
- import * as backend from './backend/backend_protocol'
2
- import * as composedBackend from './backend/composed_backend_protocol'
3
- import * as domlikeBackend from './backend/domlike_backend_protocol'
4
- import { StyleScopeId, StyleScopeManager } from './class_list'
5
- import { Context as BackendContext } from './backend/backend_protocol'
6
- import { TemplateEngine } from './template_engine'
7
- import { ComponentSpace } from './component_space'
8
- import { GlassEaselTemplateEngine } from './tmpl'
9
- import { GeneralComponent, GeneralBackendContext } from '.'
10
- import { BM } from './backend/mode'
1
+ import { type GeneralBackendContext } from './backend'
2
+ import { type StyleScopeId } from './class_list'
3
+ import { type GeneralComponent } from './component'
4
+ import { type ComponentSpace } from './component_space'
5
+ import { type DevtoolInterface } from './devtool'
6
+ import { type TemplateEngine } from './template_engine'
7
+
8
+ export const ENV = {
9
+ DEV: !(typeof process && process.env.NODE_ENV === 'production'),
10
+ }
11
11
 
12
12
  /**
13
13
  * The deep copy strategy
@@ -40,33 +40,6 @@ export enum DeepCopyKind {
40
40
  SimpleWithRecursion = 'simple-recursion',
41
41
  }
42
42
 
43
- let defaultComponentSpace: ComponentSpace | null = null
44
-
45
- export const getDefaultComponentSpace = (): ComponentSpace => {
46
- if (defaultComponentSpace) {
47
- return defaultComponentSpace
48
- }
49
- const cs = new ComponentSpace()
50
- defaultComponentSpace = cs
51
- return cs
52
- }
53
-
54
- let defaultBackendContext: GeneralBackendContext | null = null
55
-
56
- export const getDefaultBackendContext = (): GeneralBackendContext => {
57
- if (defaultBackendContext) return defaultBackendContext
58
- let c: GeneralBackendContext
59
- if (BM.DOMLIKE) {
60
- c = new domlikeBackend.CurrentWindowBackendContext()
61
- } else if (BM.COMPOSED) {
62
- c = new composedBackend.EmptyComposedBackendContext()
63
- } else {
64
- c = new backend.EmptyBackendContext()
65
- }
66
- defaultBackendContext = c
67
- return c
68
- }
69
-
70
43
  /**
71
44
  * Options for a component
72
45
  */
@@ -114,8 +87,8 @@ export type ComponentOptions = {
114
87
  export type NormalizedComponentOptions = {
115
88
  externalComponent: boolean
116
89
  hostNodeTagName: string
117
- templateEngine: TemplateEngine
118
- styleScope: StyleScopeId
90
+ templateEngine: TemplateEngine | null
91
+ styleScope: StyleScopeId | null
119
92
  extraStyleScope: StyleScopeId | null
120
93
  multipleSlots: boolean
121
94
  dynamicSlots: boolean
@@ -144,7 +117,9 @@ export type EnvironmentOptions = {
144
117
  /** Write some extra attributes to DOM backend (for testing) */
145
118
  writeExtraInfoToAttr: boolean
146
119
  /** The default backend context */
147
- backendContext: BackendContext | null
120
+ backendContext: GeneralBackendContext | null
121
+ /** The devtool interface */
122
+ devtool: DevtoolInterface | null
148
123
  }
149
124
 
150
125
  /**
@@ -153,8 +128,8 @@ export type EnvironmentOptions = {
153
128
  export const globalOptions: NormalizedComponentOptions & EnvironmentOptions = {
154
129
  defaultComponentSpace: null,
155
130
  externalComponent: false,
156
- templateEngine: new GlassEaselTemplateEngine(),
157
- styleScope: StyleScopeManager.globalScope(),
131
+ templateEngine: null,
132
+ styleScope: null,
158
133
  extraStyleScope: null,
159
134
  hostNodeTagName: 'wx-x',
160
135
  multipleSlots: false,
@@ -174,6 +149,7 @@ export const globalOptions: NormalizedComponentOptions & EnvironmentOptions = {
174
149
  throwGlobalError: false,
175
150
  writeExtraInfoToAttr: false,
176
151
  backendContext: null,
152
+ devtool: null,
177
153
  }
178
154
 
179
155
  export const normalizeComponentOptions = (