@motifx/core 1.1.0 → 1.2.0-rc.1

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/dist/index.umd.js CHANGED
@@ -286,9 +286,17 @@
286
286
  MJX121: (compiled, runtime) => `This code was compiled for compiler contract ${compiled}, but the @motifx/core runtime implements contract ${runtime}. Install matching versions of @motifx/compiler and @motifx/core, and rebuild packages that ship compiled JSX.`,
287
287
  MJX122: (hook) => `The component ${hook} hook threw.`,
288
288
  MJX123: (event) => `The '${event}' event handler threw.`,
289
- MJX124: () => `A spread object on a DOM tag cannot set innerHTML; the key was ignored. Use x-html for trusted HTML.`,
289
+ MJX124: (key) => `A spread object on a DOM tag cannot set ${key}; the key was ignored. Write it on the tag, or use x-html, for HTML you trust.`,
290
290
  MJX125: (key) => `A spread object on a DOM tag cannot set a javascript: URL on '${key}'; the value was ignored. Write the attribute on the tag if it is intended.`,
291
291
  MJX126: () => `Lazy: loading the component failed and no Fallbackview is set; the host was cleared.`,
292
+ MJX127: (got) => got === 'module'
293
+ ? `The loaded module has no default export. Export the component as default, or map it: () => import('./X').then(m => m.X).`
294
+ : `The loaded value is not a component (got ${got}). Return a component class, a function component, an Options API factory or a component instance.`,
295
+ MJX128: (cls, member, how) => how === 'method'
296
+ ? `${cls} overrides ${member} without calling super.${member}; MotifJS relies on this ComponentBase member. Rename your member, or call super.${member} in the override.`
297
+ : how === 'field'
298
+ ? `${cls} defines '${member}' as an instance field, which hides the ComponentBase member MotifJS relies on. Rename your field.`
299
+ : `${cls} replaces '${member}', which MotifJS created for the component (a class field or an assignment with that name). Rename your member.`,
292
300
  MJX201: () => `ListBinding: renderFn must return a component instance, a component class, or a factory function.`,
293
301
  MJX202: (key, index) => `ListBinding: duplicate key "${String(key)}" at index ${index}. Rows are matched by the item object, not by key, so rendering is not affected; keep keys unique so they identify items.`,
294
302
  MJX203: (max) => `An effect ran ${max} times in one flush and keeps triggering itself; it is skipped for the rest of this flush. It probably writes a value it reads (for example state.n++). Wrap the write in untracked(...).`,
@@ -1867,6 +1875,9 @@
1867
1875
  }
1868
1876
  }
1869
1877
 
1878
+ function resolveValue(value) {
1879
+ return typeof value === 'function' ? resolveValue(value()) : value;
1880
+ }
1870
1881
  function isWritablePathKey(target, key) {
1871
1882
  if (key === '__proto__')
1872
1883
  return false;
@@ -1950,7 +1961,7 @@
1950
1961
  return binding;
1951
1962
  }
1952
1963
  display(predicate) {
1953
- const binding = new Binding(this._component, 'isWait', () => !predicate());
1964
+ const binding = new Binding(this._component, 'isWait', () => !resolveValue(predicate()));
1954
1965
  this._items.push(binding);
1955
1966
  if (this._component.isBuilt) {
1956
1967
  binding.activate();
@@ -4668,6 +4679,61 @@
4668
4679
  return true;
4669
4680
  return component._base.emiters.hasListeners(lowerName);
4670
4681
  }
4682
+ const RESERVED_METHODS = ['build', 'setState', 'reState', 'setText', 'style', 'dispose', 'disposeAsync', 'using', 'doWork', 'getService', '$', 'useModel', 'context', 'siblings', 'serviceProvider', 'isWait'];
4683
+ const checkedComponentClasses = new WeakSet();
4684
+ function callsSuper(fn, name) {
4685
+ if (typeof fn !== 'function')
4686
+ return false;
4687
+ const escaped = name.replace(/\$/g, '\\$');
4688
+ return new RegExp(`\\bsuper\\s*(\\.\\s*${escaped}(?![\\w$])|\\[)`).test(Function.prototype.toString.call(fn));
4689
+ }
4690
+ function reservedMemberProblems(c) {
4691
+ const problems = [];
4692
+ const own = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
4693
+ for (const name of RESERVED_METHODS) {
4694
+ if (own(c, name)) {
4695
+ problems.push([name, 'field']);
4696
+ continue;
4697
+ }
4698
+ for (let p = Object.getPrototypeOf(c); p && p !== ComponentBase.prototype; p = Object.getPrototypeOf(p)) {
4699
+ const d = Object.getOwnPropertyDescriptor(p, name);
4700
+ if (!d)
4701
+ continue;
4702
+ const fns = 'value' in d ? [d.value] : [d.get, d.set].filter(Boolean);
4703
+ if (!fns.some(fn => callsSuper(fn, name)))
4704
+ problems.push([name, 'method']);
4705
+ break;
4706
+ }
4707
+ }
4708
+ const anyC = c;
4709
+ if (!(anyC.motif instanceof ComponentMotif))
4710
+ problems.push(['motif', 'replaced']);
4711
+ if (!(anyC.controls instanceof ControlCollection))
4712
+ problems.push(['controls', 'replaced']);
4713
+ if (!(anyC.class instanceof controlClass))
4714
+ problems.push(['class', 'replaced']);
4715
+ if (!(anyC.attr instanceof controlAttribute))
4716
+ problems.push(['attr', 'replaced']);
4717
+ if (!(anyC.bindings instanceof BindingCollection))
4718
+ problems.push(['bindings', 'replaced']);
4719
+ if (anyC.element != null && typeof Node !== 'undefined' && !(anyC.element instanceof Node))
4720
+ problems.push(['element', 'replaced']);
4721
+ if (anyC.parent != null && !(anyC.parent instanceof ComponentBase))
4722
+ problems.push(['parent', 'replaced']);
4723
+ return problems;
4724
+ }
4725
+ function checkReservedMembers(c) {
4726
+ if (!isDevLike())
4727
+ return;
4728
+ const ctor = c?.constructor;
4729
+ if (typeof ctor !== 'function' || checkedComponentClasses.has(ctor))
4730
+ return;
4731
+ checkedComponentClasses.add(ctor);
4732
+ const name = ctor.name || 'An anonymous component class';
4733
+ for (const [member, how] of reservedMemberProblems(c)) {
4734
+ reportWarning('MJX128', [name, member, how]);
4735
+ }
4736
+ }
4671
4737
  const ComponentHelper = {
4672
4738
  callInitializeComponent(component) {
4673
4739
  const sender = component;
@@ -5238,7 +5304,7 @@
5238
5304
  }
5239
5305
  function detachDomWithAnimation(c) {
5240
5306
  const node = c.element;
5241
- if (!node)
5307
+ if (!node || c._keepElementOnDispose === true)
5242
5308
  return;
5243
5309
  const opts = c.motif.options;
5244
5310
  const t = opts?.[TRANSITION_SLOT];
@@ -5268,7 +5334,7 @@
5268
5334
  }
5269
5335
  async function detachDomWithAnimationAsync(c) {
5270
5336
  const node = c.element;
5271
- if (!node)
5337
+ if (!node || c._keepElementOnDispose === true)
5272
5338
  return;
5273
5339
  const opts = c.motif.options;
5274
5340
  const t = opts?.[TRANSITION_SLOT];
@@ -5431,8 +5497,24 @@
5431
5497
  }
5432
5498
  return true;
5433
5499
  }
5500
+ const teardownApplications = new WeakMap();
5501
+ function owningApplication(c) {
5502
+ for (let p = c; p; p = p.parent) {
5503
+ if (p.application)
5504
+ return p.application;
5505
+ const recorded = teardownApplications.get(p);
5506
+ if (recorded)
5507
+ return recorded;
5508
+ }
5509
+ return Application.main ?? null;
5510
+ }
5434
5511
  function disposePrefix(c, options, asChild) {
5435
5512
  const ctx = asChild ? 'disposeAsync' : 'dispose';
5513
+ if (Application._disposingCount > 0) {
5514
+ const app = owningApplication(c);
5515
+ if (app && app.state === 'disposing')
5516
+ teardownApplications.set(c, app);
5517
+ }
5436
5518
  if (!asChild && options?.skipLeaveTransition) {
5437
5519
  c.motif.options.transition.skipNextLeave = true;
5438
5520
  }
@@ -5816,7 +5898,7 @@
5816
5898
  _scopedContext;
5817
5899
  get context() {
5818
5900
  const parentCtx = this.parent?.context;
5819
- const app = parentCtx?.[RAW_APPLICATION] ?? parentCtx ?? Application.main;
5901
+ const app = parentCtx?.[RAW_APPLICATION] ?? parentCtx ?? teardownApplications.get(this) ?? Application.main;
5820
5902
  if (!app) {
5821
5903
  return app;
5822
5904
  }
@@ -5838,6 +5920,7 @@
5838
5920
  return () => { this._disposables.detach(d); off(); };
5839
5921
  }
5840
5922
  build(building = true) {
5923
+ checkReservedMembers(this);
5841
5924
  ComponentHelper.callConfigured(this);
5842
5925
  this._base._activatePreBindings();
5843
5926
  if (this.isDisposed || !this.element || this.isWait) {
@@ -6312,7 +6395,7 @@
6312
6395
  if (mods.includes("stop")) {
6313
6396
  stop();
6314
6397
  }
6315
- if (res === false || (res && res.cancel === true)) {
6398
+ if (res && res.cancel === true) {
6316
6399
  prevent();
6317
6400
  stop();
6318
6401
  }
@@ -6519,6 +6602,9 @@
6519
6602
  const p = c.provider;
6520
6603
  if (p)
6521
6604
  return p;
6605
+ const recorded = teardownApplications.get(c);
6606
+ if (recorded)
6607
+ return recorded.state === 'disposed' ? null : recorded.provider;
6522
6608
  c = c.parent;
6523
6609
  }
6524
6610
  try {
@@ -6863,6 +6949,7 @@
6863
6949
  'ref', 'key', 'indexkey', 'inject', 'options', 'props', 'settings', 'isSvg',
6864
6950
  'childs', 'initializeComponent', 'runover', 'transition', 'preconfig', 'nodes', 'onElementCreating'
6865
6951
  ]);
6952
+ const SPREAD_HTML_KEYS = new Set(['innerhtml', 'srcdoc']);
6866
6953
  const SPREAD_URL_ATTRIBUTES = new Set(['href', 'src', 'action', 'formaction', 'xlink:href']);
6867
6954
  const JAVASCRIPT_URL = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i;
6868
6955
  function isJavascriptUrl(value) {
@@ -6911,11 +6998,12 @@
6911
6998
  }
6912
6999
  if (typeof v === 'function' && v.length > 0)
6913
7000
  continue;
6914
- if (key === 'innerHTML') {
6915
- reportWarning('MJX124', []);
7001
+ const lowerKey = key.toLowerCase();
7002
+ if (SPREAD_HTML_KEYS.has(lowerKey)) {
7003
+ reportWarning('MJX124', [key]);
6916
7004
  continue;
6917
7005
  }
6918
- if (SPREAD_URL_ATTRIBUTES.has(key.toLowerCase())) {
7006
+ if (SPREAD_URL_ATTRIBUTES.has(lowerKey)) {
6919
7007
  if (typeof v === 'function') {
6920
7008
  v = guardSpreadUrl(key, v);
6921
7009
  }
@@ -7104,6 +7192,9 @@
7104
7192
  }
7105
7193
  if (elementOrParams instanceof Function) {
7106
7194
  elementOrParams = resolveComponent(elementOrParams, options);
7195
+ if (isOptionsObject(elementOrParams)) {
7196
+ return materializeOptionsObject(elementOrParams, options);
7197
+ }
7107
7198
  }
7108
7199
  if (Array.isArray(elementOrParams)) {
7109
7200
  const letter = CreateFragment();
@@ -7293,6 +7384,40 @@
7293
7384
  }
7294
7385
  return new Component(element, props);
7295
7386
  }
7387
+ function isOptionsObject(value) {
7388
+ return typeof value == "object" && value !== null && !(value instanceof ComponentBase) && 'el' in value;
7389
+ }
7390
+ function unwrapModule(result) {
7391
+ if (result && typeof result === "object" && !(result instanceof ComponentBase) && result.default != null) {
7392
+ return result.default;
7393
+ }
7394
+ return result;
7395
+ }
7396
+ function describeLoaded(value) {
7397
+ if (value === null)
7398
+ return 'null';
7399
+ if (Array.isArray(value))
7400
+ return 'array';
7401
+ if (typeof value === "object" && (Object.prototype.toString.call(value) === '[object Module]' || value.__esModule))
7402
+ return 'module';
7403
+ return typeof value;
7404
+ }
7405
+ function assertLoadedComponent(value) {
7406
+ if (value === null || typeof value !== "object")
7407
+ return;
7408
+ if (value instanceof ComponentBase || Array.isArray(value) || value instanceof Node)
7409
+ return;
7410
+ if (typeof value.then === "function")
7411
+ return;
7412
+ throw motifError('MJX127', describeLoaded(value));
7413
+ }
7414
+ function resolveToComponent(input, props) {
7415
+ const resolved = resolveComponent(input, props);
7416
+ if (isOptionsObject(resolved)) {
7417
+ return materializeOptionsObject(resolved, undefined);
7418
+ }
7419
+ return resolved;
7420
+ }
7296
7421
  function materializeOptionsObject(spec, props) {
7297
7422
  const result = motifComponent(spec.el, props);
7298
7423
  Object.getOwnPropertyNames(spec).forEach(key => {
@@ -7527,6 +7652,7 @@
7527
7652
  if (typeof control == 'string' || typeof control == 'number' || typeof control == 'boolean' || typeof control == 'bigint') {
7528
7653
  control = new Component(dom.createTextNode(control), null);
7529
7654
  }
7655
+ checkReservedMembers(control);
7530
7656
  if (control.parent) {
7531
7657
  control.parent.controls.detach(control);
7532
7658
  }
@@ -7898,10 +8024,7 @@
7898
8024
  return { count: 0, delayMs: 0, whenOnline: false };
7899
8025
  }
7900
8026
  function defaultMapper(result) {
7901
- if (result && typeof result === "object" && typeof result.default === "function") {
7902
- return result.default;
7903
- }
7904
- return result;
8027
+ return unwrapModule(result);
7905
8028
  }
7906
8029
  function Lazy(props) {
7907
8030
  const opts = (props && props.options) || {};
@@ -7930,7 +8053,7 @@
7930
8053
  catch { }
7931
8054
  const initial = opts.Placeholderview ?? opts.Loaderview;
7932
8055
  if (initial != null) {
7933
- frame.navigate(resolveComponent(initial));
8056
+ frame.navigate(resolveToComponent(initial));
7934
8057
  }
7935
8058
  const attemptLoad = () => {
7936
8059
  if (!opts.timeoutMs && !opts.signal) {
@@ -8056,6 +8179,36 @@
8056
8179
  };
8057
8180
  const loadPromise = retry.count > 0 ? loadWithRetry() : attemptLoad();
8058
8181
  const startTs = Date.now();
8182
+ const fail = (err) => {
8183
+ try {
8184
+ opts.onError?.(err);
8185
+ }
8186
+ catch { /* swallow */ }
8187
+ if (opts.signal?.aborted)
8188
+ return;
8189
+ if (opts.Fallbackview != null) {
8190
+ frame.navigate(resolveToComponent(opts.Fallbackview));
8191
+ }
8192
+ else {
8193
+ reportError('MJX126', err);
8194
+ try {
8195
+ frame.motif.clear().catch(() => { });
8196
+ }
8197
+ catch { }
8198
+ }
8199
+ };
8200
+ const place = (target) => {
8201
+ let component;
8202
+ try {
8203
+ component = resolveToComponent(target);
8204
+ assertLoadedComponent(component);
8205
+ }
8206
+ catch (err) {
8207
+ fail(err);
8208
+ return;
8209
+ }
8210
+ frame.navigate(component);
8211
+ };
8059
8212
  loadPromise
8060
8213
  .then((result) => {
8061
8214
  if (opts.signal?.aborted) {
@@ -8069,7 +8222,7 @@
8069
8222
  if (remaining > 0) {
8070
8223
  const id = trackTimer(setTimeout(() => {
8071
8224
  if (!opts.signal?.aborted) {
8072
- frame.navigate(resolveComponent(target));
8225
+ place(target);
8073
8226
  }
8074
8227
  }, remaining));
8075
8228
  if (opts.signal) {
@@ -8085,27 +8238,10 @@
8085
8238
  }
8086
8239
  }
8087
8240
  else {
8088
- frame.navigate(resolveComponent(target));
8241
+ place(target);
8089
8242
  }
8090
8243
  })
8091
- .catch((err) => {
8092
- try {
8093
- opts.onError?.(err);
8094
- }
8095
- catch { /* swallow */ }
8096
- if (opts.signal?.aborted)
8097
- return;
8098
- if (opts.Fallbackview != null) {
8099
- frame.navigate(resolveComponent(opts.Fallbackview));
8100
- }
8101
- else {
8102
- reportError('MJX126', err);
8103
- try {
8104
- frame.motif.clear().catch(() => { });
8105
- }
8106
- catch { }
8107
- }
8108
- });
8244
+ .catch(fail);
8109
8245
  return frame;
8110
8246
  }
8111
8247
 
@@ -8770,6 +8906,144 @@
8770
8906
  }
8771
8907
  }
8772
8908
 
8909
+ const KEYS_KEY = Symbol('');
8910
+ function changed(target, key, keysChanged) {
8911
+ trigger(target, key);
8912
+ trigger(target, ITERATE_KEY);
8913
+ if (keysChanged)
8914
+ trigger(target, KEYS_KEY);
8915
+ }
8916
+ function lookupKey(target, key) {
8917
+ return target.has(key) ? key : getRaw(key);
8918
+ }
8919
+ function wrapIterator(source, convert) {
8920
+ return {
8921
+ next() {
8922
+ const step = source.next();
8923
+ return step.done ? step : { value: convert(step.value), done: false };
8924
+ },
8925
+ [Symbol.iterator]() {
8926
+ return this;
8927
+ },
8928
+ };
8929
+ }
8930
+ function createCollectionMethods(engine) {
8931
+ const wrap = (value) => isObject(value) ? engine.reactive(value) : value;
8932
+ const wrapEntry = (target) => target instanceof Map
8933
+ ? ([key, value]) => [key, wrap(value)]
8934
+ : ([value]) => { const item = wrap(value); return [item, item]; };
8935
+ return {
8936
+ get(key) {
8937
+ const target = getRaw(this);
8938
+ const found = lookupKey(target, key);
8939
+ track(target, found);
8940
+ return wrap(target.get(found));
8941
+ },
8942
+ has(key) {
8943
+ const target = getRaw(this);
8944
+ const found = lookupKey(target, key);
8945
+ track(target, found);
8946
+ return target.has(found);
8947
+ },
8948
+ set(key, value) {
8949
+ const target = getRaw(this);
8950
+ const stored = lookupKey(target, key);
8951
+ const raw = getRaw(value);
8952
+ const existed = target.has(stored);
8953
+ const previous = target.get(stored);
8954
+ target.set(stored, raw);
8955
+ if (!existed)
8956
+ changed(target, stored, true);
8957
+ else if (!Object.is(previous, raw))
8958
+ changed(target, stored, false);
8959
+ return this;
8960
+ },
8961
+ add(value) {
8962
+ const target = getRaw(this);
8963
+ const stored = lookupKey(target, value);
8964
+ if (!target.has(stored)) {
8965
+ target.add(stored);
8966
+ changed(target, stored, true);
8967
+ }
8968
+ return this;
8969
+ },
8970
+ delete(key) {
8971
+ const target = getRaw(this);
8972
+ const found = lookupKey(target, key);
8973
+ const removed = target.delete(found);
8974
+ if (removed)
8975
+ changed(target, found, true);
8976
+ return removed;
8977
+ },
8978
+ clear() {
8979
+ const target = getRaw(this);
8980
+ if (target.size === 0)
8981
+ return;
8982
+ const keys = Array.from(target.keys());
8983
+ target.clear();
8984
+ for (const key of keys)
8985
+ trigger(target, key);
8986
+ trigger(target, ITERATE_KEY);
8987
+ trigger(target, KEYS_KEY);
8988
+ },
8989
+ forEach(callback, thisArg) {
8990
+ const target = getRaw(this);
8991
+ track(target, ITERATE_KEY);
8992
+ const owner = this;
8993
+ const isMap = target instanceof Map;
8994
+ target.forEach((value, key) => {
8995
+ const item = wrap(value);
8996
+ callback.call(thisArg, item, isMap ? key : item, owner);
8997
+ });
8998
+ },
8999
+ keys() {
9000
+ const target = getRaw(this);
9001
+ if (target instanceof Map) {
9002
+ track(target, KEYS_KEY);
9003
+ return target.keys();
9004
+ }
9005
+ track(target, ITERATE_KEY);
9006
+ return wrapIterator(target.keys(), wrap);
9007
+ },
9008
+ values() {
9009
+ const target = getRaw(this);
9010
+ track(target, ITERATE_KEY);
9011
+ return wrapIterator(target.values(), wrap);
9012
+ },
9013
+ entries() {
9014
+ const target = getRaw(this);
9015
+ track(target, ITERATE_KEY);
9016
+ return wrapIterator(target.entries(), wrapEntry(target));
9017
+ },
9018
+ [Symbol.iterator]() {
9019
+ const target = getRaw(this);
9020
+ track(target, ITERATE_KEY);
9021
+ return target instanceof Map
9022
+ ? wrapIterator(target.entries(), wrapEntry(target))
9023
+ : wrapIterator(target.values(), wrap);
9024
+ },
9025
+ };
9026
+ }
9027
+ function createCollectionHandler(engine) {
9028
+ const methods = createCollectionMethods(engine);
9029
+ return {
9030
+ get(target, key, receiver) {
9031
+ const meta = readMeta(engine, target, key, receiver);
9032
+ if (meta !== NOT_META)
9033
+ return meta;
9034
+ if (key === 'size') {
9035
+ track(target, ITERATE_KEY);
9036
+ return target.size;
9037
+ }
9038
+ if ((typeof key === 'string' || key === Symbol.iterator) && hasOwn(methods, key) && key in target) {
9039
+ return methods[key];
9040
+ }
9041
+ const value = Reflect.get(target, key, target);
9042
+ return typeof value === 'function' ? value.bind(target) : value;
9043
+ },
9044
+ };
9045
+ }
9046
+
8773
9047
  const ReactiveEngineMapper = new WeakSet();
8774
9048
  const AllreactiveMap = new WeakMap();
8775
9049
  function armgetter() { return AllreactiveMap; }
@@ -8808,12 +9082,13 @@
8808
9082
  deleteProperty: createDelete(),
8809
9083
  ownKeys: createOwn()
8810
9084
  };
9085
+ collectionHandler = createCollectionHandler(this);
8811
9086
  reactive(model) {
8812
9087
  if (!isObject(model)) {
8813
9088
  model = { value: model };
8814
9089
  }
8815
9090
  const targetType = getTargetType(model);
8816
- if (targetType === 0 /* TargetType.SYSTEM */ || targetType === 2 /* TargetType.COLLECTION */ || 0 /* TargetType.INVALID */) {
9091
+ if (targetType === 0 /* TargetType.SYSTEM */ || 0 /* TargetType.INVALID */) {
8817
9092
  return model;
8818
9093
  }
8819
9094
  let existingProxy = AllreactiveMap.get(model);
@@ -8825,7 +9100,12 @@
8825
9100
  return existingProxy;
8826
9101
  }
8827
9102
  // if (targetType === TargetType.INVALID) {
8828
- if (Array.isArray(model)) {
9103
+ if (targetType === 2 /* TargetType.COLLECTION */) {
9104
+ var proxy = new Proxy(model, this.collectionHandler);
9105
+ AllreactiveMap.set(model, proxy);
9106
+ return proxy;
9107
+ }
9108
+ else if (Array.isArray(model)) {
8829
9109
  var proxy = new Proxy(model, this.arrayHandler);
8830
9110
  // var original = Object.getPrototypeOf(proxy);
8831
9111
  // original["copy"] = () => { return model; }
@@ -11814,18 +12094,16 @@
11814
12094
  }
11815
12095
  let val = control;
11816
12096
  if (val instanceof Promise) {
11817
- val = await val.then((result) => {
11818
- return result.default ? result.default : result;
11819
- });
12097
+ val = unwrapModule(await val);
11820
12098
  }
11821
12099
  instance = this._construct(scope, route, () => this._resolveFrom(scope, val));
11822
12100
  if (instance) {
11823
12101
  return instance;
11824
12102
  }
11825
12103
  if (typeof val === 'function') {
11826
- return this.parseControl(this._construct(scope, route, () => resolveComponent(val, this.application)), scope, route);
12104
+ return this.parseControl(this._construct(scope, route, () => resolveToComponent(val, this.application)), scope, route);
11827
12105
  }
11828
- return val;
12106
+ return resolveToComponent(val);
11829
12107
  }
11830
12108
  _resolveFrom(scope, token) {
11831
12109
  const provider = scope ?? this._rootProvider();
@@ -11846,6 +12124,7 @@
11846
12124
  }
11847
12125
  async _instanceCreator(control, scope, route) {
11848
12126
  let val = await this.parseControl(control, scope, route);
12127
+ assertLoadedComponent(val);
11849
12128
  // if (val instanceof Promise) {
11850
12129
  // return result.default ? result.default : result;
11851
12130
  // if (typeof val === 'function') {
@@ -12882,10 +13161,11 @@
12882
13161
  catch { }
12883
13162
  this._scroll = null;
12884
13163
  this._historyStamp = null;
13164
+ let done = Promise.resolve();
12885
13165
  try {
12886
13166
  // keepAlive önbelleğindeki örnekleri bırak
12887
13167
  try {
12888
- void this.routingEngine.dispose();
13168
+ done = this.routingEngine.dispose();
12889
13169
  }
12890
13170
  catch { }
12891
13171
  if (this._navHandler) {
@@ -12905,6 +13185,7 @@
12905
13185
  }
12906
13186
  }
12907
13187
  catch { }
13188
+ return done;
12908
13189
  }
12909
13190
  }
12910
13191
 
@@ -12990,7 +13271,7 @@
12990
13271
  class ApplicationBuilder {
12991
13272
  services = new ServiceCollection();
12992
13273
  constructor() {
12993
- if (_globalApplication || startedApplicationBuilder) {
13274
+ if ((_globalApplication && _globalApplication.state !== 'disposing') || startedApplicationBuilder) {
12994
13275
  throw new MotifError('MJX405', formatMotifMessage('MJX405'), { cause: _globalApplication });
12995
13276
  }
12996
13277
  startedApplicationBuilder = true;
@@ -13023,6 +13304,12 @@
13023
13304
  constructor(provider) {
13024
13305
  this.provider = provider;
13025
13306
  }
13307
+ static _disposingCount = 0;
13308
+ _state = 'initializing';
13309
+ _disposing;
13310
+ get state() {
13311
+ return this._state;
13312
+ }
13026
13313
  _middlewares = [];
13027
13314
  _beforeEachGuards = [];
13028
13315
  _routerState = new RouterState();
@@ -13049,9 +13336,11 @@
13049
13336
  target = host;
13050
13337
  }
13051
13338
  let rootInstance = appRoot;
13339
+ this._state = 'running';
13052
13340
  const AppShell = new Component(target);
13053
13341
  this.appShell = AppShell;
13054
13342
  safeCallSilent(() => {
13343
+ AppShell._keepElementOnDispose = true;
13055
13344
  AppShell.application = this;
13056
13345
  AppShell.provider = this.provider;
13057
13346
  }, 'Application.run.setupAppShell');
@@ -13086,10 +13375,14 @@
13086
13375
  this.appShell.element?.appendChild(component);
13087
13376
  }
13088
13377
  dispose() {
13378
+ if (this._disposing)
13379
+ return this._disposing;
13380
+ this._state = 'disposing';
13381
+ Application._disposingCount++;
13089
13382
  startedApplicationBuilder = false;
13383
+ let routerDone;
13090
13384
  safeCallSilent(() => { this._removeLifecycleListeners(); }, 'Application.dispose.lifecycle');
13091
- safeCallSilent(() => { this.urlRoutingModule?.dispose?.(); }, 'Application.dispose.router');
13092
- safeCallSilent(() => { this.provider.dispose(); }, 'Application.dispose.preDispose');
13385
+ safeCallSilent(() => { routerDone = this.urlRoutingModule?.dispose?.(); }, 'Application.dispose.router');
13093
13386
  safeCallSilent(() => { engine.stopGc(); }, 'Application.dispose.gcStop');
13094
13387
  safeCallSilent(() => {
13095
13388
  try {
@@ -13102,7 +13395,31 @@
13102
13395
  catch { /* ignore */ }
13103
13396
  }, 'Application.dispose.resetUrl');
13104
13397
  transitionSettings.mode = 'concurrent';
13105
- _globalApplication = null;
13398
+ const shell = this.appShell;
13399
+ return this._disposing = (async () => {
13400
+ try {
13401
+ await routerDone;
13402
+ }
13403
+ catch (error) {
13404
+ reportError('MJX307', error);
13405
+ }
13406
+ if (shell && !shell.isDisposed) {
13407
+ try {
13408
+ await shell.dispose();
13409
+ }
13410
+ catch (error) {
13411
+ reportError('MJX307', error);
13412
+ }
13413
+ }
13414
+ try {
13415
+ await this.provider.dispose();
13416
+ }
13417
+ catch { }
13418
+ if (_globalApplication === this)
13419
+ _globalApplication = null;
13420
+ this._state = 'disposed';
13421
+ Application._disposingCount--;
13422
+ })();
13106
13423
  }
13107
13424
  useTransitions(options) {
13108
13425
  if (isTransitionMode(options?.mode))