@odoo/owl 2.0.0-beta-14 → 2.0.0-beta-17
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/owl.cjs.js +142 -124
- package/dist/owl.es.js +142 -125
- package/dist/owl.iife.js +142 -124
- package/dist/owl.iife.min.js +1 -1
- package/dist/types/compiler/inline_expressions.d.ts +0 -22
- package/dist/types/owl.d.ts +5 -2
- package/dist/types/runtime/component_node.d.ts +0 -1
- package/dist/types/runtime/error_handling.d.ts +3 -0
- package/dist/types/runtime/index.d.ts +2 -0
- package/dist/types/runtime/template_helpers.d.ts +2 -0
- package/package.json +1 -2
package/dist/owl.es.js
CHANGED
|
@@ -77,6 +77,68 @@ function toggler(key, child) {
|
|
|
77
77
|
return new VToggler(key, child);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// Custom error class that wraps error that happen in the owl lifecycle
|
|
81
|
+
class OwlError extends Error {
|
|
82
|
+
}
|
|
83
|
+
// Maps fibers to thrown errors
|
|
84
|
+
const fibersInError = new WeakMap();
|
|
85
|
+
const nodeErrorHandlers = new WeakMap();
|
|
86
|
+
function _handleError(node, error) {
|
|
87
|
+
if (!node) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const fiber = node.fiber;
|
|
91
|
+
if (fiber) {
|
|
92
|
+
fibersInError.set(fiber, error);
|
|
93
|
+
}
|
|
94
|
+
const errorHandlers = nodeErrorHandlers.get(node);
|
|
95
|
+
if (errorHandlers) {
|
|
96
|
+
let handled = false;
|
|
97
|
+
// execute in the opposite order
|
|
98
|
+
for (let i = errorHandlers.length - 1; i >= 0; i--) {
|
|
99
|
+
try {
|
|
100
|
+
errorHandlers[i](error);
|
|
101
|
+
handled = true;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
error = e;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (handled) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return _handleError(node.parent, error);
|
|
113
|
+
}
|
|
114
|
+
function handleError(params) {
|
|
115
|
+
let { error } = params;
|
|
116
|
+
// Wrap error if it wasn't wrapped by wrapError (ie when not in dev mode)
|
|
117
|
+
if (!(error instanceof OwlError)) {
|
|
118
|
+
error = Object.assign(new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`), { cause: error });
|
|
119
|
+
}
|
|
120
|
+
const node = "node" in params ? params.node : params.fiber.node;
|
|
121
|
+
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
|
122
|
+
// resets the fibers on components if possible. This is important so that
|
|
123
|
+
// new renderings can be properly included in the initial one, if any.
|
|
124
|
+
let current = fiber;
|
|
125
|
+
do {
|
|
126
|
+
current.node.fiber = current;
|
|
127
|
+
current = current.parent;
|
|
128
|
+
} while (current);
|
|
129
|
+
fibersInError.set(fiber.root, error);
|
|
130
|
+
const handled = _handleError(node, error);
|
|
131
|
+
if (!handled) {
|
|
132
|
+
console.warn(`[Owl] Unhandled error. Destroying the root component`);
|
|
133
|
+
try {
|
|
134
|
+
node.app.destroy();
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error(e);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
80
142
|
const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype;
|
|
81
143
|
const tokenList = DOMTokenList.prototype;
|
|
82
144
|
const tokenListAdd = tokenList.add;
|
|
@@ -698,7 +760,7 @@ function buildTree(node, parent = null, domParentTree = null) {
|
|
|
698
760
|
};
|
|
699
761
|
}
|
|
700
762
|
}
|
|
701
|
-
throw new
|
|
763
|
+
throw new OwlError("boom");
|
|
702
764
|
}
|
|
703
765
|
function addRef(tree) {
|
|
704
766
|
tree.isRef = true;
|
|
@@ -1382,61 +1444,6 @@ function remove(vnode, withBeforeRemove = false) {
|
|
|
1382
1444
|
vnode.remove();
|
|
1383
1445
|
}
|
|
1384
1446
|
|
|
1385
|
-
// Maps fibers to thrown errors
|
|
1386
|
-
const fibersInError = new WeakMap();
|
|
1387
|
-
const nodeErrorHandlers = new WeakMap();
|
|
1388
|
-
function _handleError(node, error) {
|
|
1389
|
-
if (!node) {
|
|
1390
|
-
return false;
|
|
1391
|
-
}
|
|
1392
|
-
const fiber = node.fiber;
|
|
1393
|
-
if (fiber) {
|
|
1394
|
-
fibersInError.set(fiber, error);
|
|
1395
|
-
}
|
|
1396
|
-
const errorHandlers = nodeErrorHandlers.get(node);
|
|
1397
|
-
if (errorHandlers) {
|
|
1398
|
-
let handled = false;
|
|
1399
|
-
// execute in the opposite order
|
|
1400
|
-
for (let i = errorHandlers.length - 1; i >= 0; i--) {
|
|
1401
|
-
try {
|
|
1402
|
-
errorHandlers[i](error);
|
|
1403
|
-
handled = true;
|
|
1404
|
-
break;
|
|
1405
|
-
}
|
|
1406
|
-
catch (e) {
|
|
1407
|
-
error = e;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
if (handled) {
|
|
1411
|
-
return true;
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
return _handleError(node.parent, error);
|
|
1415
|
-
}
|
|
1416
|
-
function handleError(params) {
|
|
1417
|
-
const error = params.error;
|
|
1418
|
-
const node = "node" in params ? params.node : params.fiber.node;
|
|
1419
|
-
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
|
1420
|
-
// resets the fibers on components if possible. This is important so that
|
|
1421
|
-
// new renderings can be properly included in the initial one, if any.
|
|
1422
|
-
let current = fiber;
|
|
1423
|
-
do {
|
|
1424
|
-
current.node.fiber = current;
|
|
1425
|
-
current = current.parent;
|
|
1426
|
-
} while (current);
|
|
1427
|
-
fibersInError.set(fiber.root, error);
|
|
1428
|
-
const handled = _handleError(node, error);
|
|
1429
|
-
if (!handled) {
|
|
1430
|
-
console.warn(`[Owl] Unhandled error. Destroying the root component`);
|
|
1431
|
-
try {
|
|
1432
|
-
node.app.destroy();
|
|
1433
|
-
}
|
|
1434
|
-
catch (e) {
|
|
1435
|
-
console.error(e);
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
1447
|
function makeChildFiber(node, parent) {
|
|
1441
1448
|
let current = node.fiber;
|
|
1442
1449
|
if (current) {
|
|
@@ -1475,7 +1482,7 @@ function makeRootFiber(node) {
|
|
|
1475
1482
|
return fiber;
|
|
1476
1483
|
}
|
|
1477
1484
|
function throwOnRender() {
|
|
1478
|
-
throw new
|
|
1485
|
+
throw new OwlError("Attempted to render cancelled fiber");
|
|
1479
1486
|
}
|
|
1480
1487
|
/**
|
|
1481
1488
|
* @returns number of not-yet rendered fibers cancelled
|
|
@@ -1852,7 +1859,7 @@ const reactiveCache = new WeakMap();
|
|
|
1852
1859
|
*/
|
|
1853
1860
|
function reactive(target, callback = () => { }) {
|
|
1854
1861
|
if (!canBeMadeReactive(target)) {
|
|
1855
|
-
throw new
|
|
1862
|
+
throw new OwlError(`Cannot make the given value reactive`);
|
|
1856
1863
|
}
|
|
1857
1864
|
if (SKIP in target) {
|
|
1858
1865
|
return target;
|
|
@@ -2120,12 +2127,18 @@ function batched(callback) {
|
|
|
2120
2127
|
};
|
|
2121
2128
|
}
|
|
2122
2129
|
function validateTarget(target) {
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2130
|
+
// Get the document and HTMLElement corresponding to the target to allow mounting in iframes
|
|
2131
|
+
const document = target && target.ownerDocument;
|
|
2132
|
+
if (document) {
|
|
2133
|
+
const HTMLElement = document.defaultView.HTMLElement;
|
|
2134
|
+
if (target instanceof HTMLElement) {
|
|
2135
|
+
if (!document.body.contains(target)) {
|
|
2136
|
+
throw new OwlError("Cannot mount a component on a detached dom node");
|
|
2137
|
+
}
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2128
2140
|
}
|
|
2141
|
+
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
|
|
2129
2142
|
}
|
|
2130
2143
|
class EventBus extends EventTarget {
|
|
2131
2144
|
trigger(name, payload) {
|
|
@@ -2145,7 +2158,7 @@ function whenReady(fn) {
|
|
|
2145
2158
|
async function loadFile(url) {
|
|
2146
2159
|
const result = await fetch(url);
|
|
2147
2160
|
if (!result.ok) {
|
|
2148
|
-
throw new
|
|
2161
|
+
throw new OwlError("Error while fetching xml templates");
|
|
2149
2162
|
}
|
|
2150
2163
|
return await result.text();
|
|
2151
2164
|
}
|
|
@@ -2167,7 +2180,7 @@ function markup(value) {
|
|
|
2167
2180
|
let currentNode = null;
|
|
2168
2181
|
function getCurrent() {
|
|
2169
2182
|
if (!currentNode) {
|
|
2170
|
-
throw new
|
|
2183
|
+
throw new OwlError("No active component (a hook function should only be called in 'setup')");
|
|
2171
2184
|
}
|
|
2172
2185
|
return currentNode;
|
|
2173
2186
|
}
|
|
@@ -2229,7 +2242,6 @@ class ComponentNode {
|
|
|
2229
2242
|
this.parent = parent;
|
|
2230
2243
|
this.props = props;
|
|
2231
2244
|
this.parentKey = parentKey;
|
|
2232
|
-
this.level = parent ? parent.level + 1 : 0;
|
|
2233
2245
|
const defaultProps = C.defaultProps;
|
|
2234
2246
|
props = Object.assign({}, props);
|
|
2235
2247
|
if (defaultProps) {
|
|
@@ -2462,17 +2474,27 @@ class ComponentNode {
|
|
|
2462
2474
|
|
|
2463
2475
|
const TIMEOUT = Symbol("timeout");
|
|
2464
2476
|
function wrapError(fn, hookName) {
|
|
2465
|
-
const error = new
|
|
2466
|
-
const timeoutError = new
|
|
2477
|
+
const error = new OwlError(`The following error occurred in ${hookName}: `);
|
|
2478
|
+
const timeoutError = new OwlError(`${hookName}'s promise hasn't resolved after 3 seconds`);
|
|
2467
2479
|
const node = getCurrent();
|
|
2468
2480
|
return (...args) => {
|
|
2481
|
+
const onError = (cause) => {
|
|
2482
|
+
error.cause = cause;
|
|
2483
|
+
if (cause instanceof Error) {
|
|
2484
|
+
error.message += `"${cause.message}"`;
|
|
2485
|
+
}
|
|
2486
|
+
else {
|
|
2487
|
+
error.message = `Something that is not an Error was thrown in ${hookName} (see this Error's "cause" property)`;
|
|
2488
|
+
}
|
|
2489
|
+
throw error;
|
|
2490
|
+
};
|
|
2469
2491
|
try {
|
|
2470
2492
|
const result = fn(...args);
|
|
2471
2493
|
if (result instanceof Promise) {
|
|
2472
2494
|
if (hookName === "onWillStart" || hookName === "onWillUpdateProps") {
|
|
2473
2495
|
const fiber = node.fiber;
|
|
2474
2496
|
Promise.race([
|
|
2475
|
-
result,
|
|
2497
|
+
result.catch(() => { }),
|
|
2476
2498
|
new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)),
|
|
2477
2499
|
]).then((res) => {
|
|
2478
2500
|
if (res === TIMEOUT && node.fiber === fiber) {
|
|
@@ -2480,21 +2502,12 @@ function wrapError(fn, hookName) {
|
|
|
2480
2502
|
}
|
|
2481
2503
|
});
|
|
2482
2504
|
}
|
|
2483
|
-
return result.catch(
|
|
2484
|
-
error.cause = cause;
|
|
2485
|
-
if (cause instanceof Error) {
|
|
2486
|
-
error.message += `"${cause.message}"`;
|
|
2487
|
-
}
|
|
2488
|
-
throw error;
|
|
2489
|
-
});
|
|
2505
|
+
return result.catch(onError);
|
|
2490
2506
|
}
|
|
2491
2507
|
return result;
|
|
2492
2508
|
}
|
|
2493
2509
|
catch (cause) {
|
|
2494
|
-
|
|
2495
|
-
error.message += `"${cause.message}"`;
|
|
2496
|
-
}
|
|
2497
|
-
throw error;
|
|
2510
|
+
onError(cause);
|
|
2498
2511
|
}
|
|
2499
2512
|
};
|
|
2500
2513
|
}
|
|
@@ -2598,7 +2611,7 @@ class VPortal extends VText {
|
|
|
2598
2611
|
}
|
|
2599
2612
|
this.target = el && el.querySelector(this.selector);
|
|
2600
2613
|
if (!this.target) {
|
|
2601
|
-
throw new
|
|
2614
|
+
throw new OwlError("invalid portal target");
|
|
2602
2615
|
}
|
|
2603
2616
|
}
|
|
2604
2617
|
this.realBDom.mount(this.target, null);
|
|
@@ -2692,7 +2705,7 @@ function toSchema(spec) {
|
|
|
2692
2705
|
function validate(obj, spec) {
|
|
2693
2706
|
let errors = validateSchema(obj, spec);
|
|
2694
2707
|
if (errors.length) {
|
|
2695
|
-
throw new
|
|
2708
|
+
throw new OwlError("Invalid object: " + errors.join(", "));
|
|
2696
2709
|
}
|
|
2697
2710
|
}
|
|
2698
2711
|
/**
|
|
@@ -2845,7 +2858,7 @@ function prepareList(collection) {
|
|
|
2845
2858
|
keys = Object.values(collection);
|
|
2846
2859
|
}
|
|
2847
2860
|
else {
|
|
2848
|
-
throw new
|
|
2861
|
+
throw new OwlError("Invalid loop expression");
|
|
2849
2862
|
}
|
|
2850
2863
|
const n = values.length;
|
|
2851
2864
|
return [keys, values, n, new Array(n)];
|
|
@@ -2951,7 +2964,7 @@ function multiRefSetter(refs, name) {
|
|
|
2951
2964
|
if (el) {
|
|
2952
2965
|
count++;
|
|
2953
2966
|
if (count > 1) {
|
|
2954
|
-
throw new
|
|
2967
|
+
throw new OwlError("Cannot have 2 elements with same ref name at the same time");
|
|
2955
2968
|
}
|
|
2956
2969
|
}
|
|
2957
2970
|
if (count === 0 || el) {
|
|
@@ -2988,13 +3001,13 @@ function validateProps(name, props, parent) {
|
|
|
2988
3001
|
: name in schema && !("*" in schema) && !isOptional(schema[name]);
|
|
2989
3002
|
for (let p in defaultProps) {
|
|
2990
3003
|
if (isMandatory(p)) {
|
|
2991
|
-
throw new
|
|
3004
|
+
throw new OwlError(`A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})`);
|
|
2992
3005
|
}
|
|
2993
3006
|
}
|
|
2994
3007
|
}
|
|
2995
3008
|
const errors = validateSchema(props, schema);
|
|
2996
3009
|
if (errors.length) {
|
|
2997
|
-
throw new
|
|
3010
|
+
throw new OwlError(`Invalid props for component '${ComponentClass.name}': ` + errors.join(", "));
|
|
2998
3011
|
}
|
|
2999
3012
|
}
|
|
3000
3013
|
const helpers = {
|
|
@@ -3015,6 +3028,7 @@ const helpers = {
|
|
|
3015
3028
|
bind,
|
|
3016
3029
|
createCatcher,
|
|
3017
3030
|
markRaw,
|
|
3031
|
+
OwlError,
|
|
3018
3032
|
};
|
|
3019
3033
|
|
|
3020
3034
|
const bdom = { text, createBlock, list, multi, html, toggler, comment };
|
|
@@ -3042,7 +3056,7 @@ function parseXML$1(xml) {
|
|
|
3042
3056
|
}
|
|
3043
3057
|
}
|
|
3044
3058
|
}
|
|
3045
|
-
throw new
|
|
3059
|
+
throw new OwlError(msg);
|
|
3046
3060
|
}
|
|
3047
3061
|
return doc;
|
|
3048
3062
|
}
|
|
@@ -3073,7 +3087,7 @@ class TemplateSet {
|
|
|
3073
3087
|
if (currentAsString === newAsString) {
|
|
3074
3088
|
return;
|
|
3075
3089
|
}
|
|
3076
|
-
throw new
|
|
3090
|
+
throw new OwlError(`Template ${name} already defined with different content`);
|
|
3077
3091
|
}
|
|
3078
3092
|
this.rawTemplates[name] = template;
|
|
3079
3093
|
}
|
|
@@ -3098,7 +3112,7 @@ class TemplateSet {
|
|
|
3098
3112
|
extraInfo = ` (for component "${componentName}")`;
|
|
3099
3113
|
}
|
|
3100
3114
|
catch { }
|
|
3101
|
-
throw new
|
|
3115
|
+
throw new OwlError(`Missing template: "${name}"${extraInfo}`);
|
|
3102
3116
|
}
|
|
3103
3117
|
const isFn = typeof rawTemplate === "function" && !(rawTemplate instanceof Element);
|
|
3104
3118
|
const templateFn = isFn ? rawTemplate : this._compileTemplate(name, rawTemplate);
|
|
@@ -3114,7 +3128,7 @@ class TemplateSet {
|
|
|
3114
3128
|
return this.templates[name];
|
|
3115
3129
|
}
|
|
3116
3130
|
_compileTemplate(name, template) {
|
|
3117
|
-
throw new
|
|
3131
|
+
throw new OwlError(`Unable to compile a template. Please use owl full build instead`);
|
|
3118
3132
|
}
|
|
3119
3133
|
callTemplate(owner, subTemplate, ctx, parent, key) {
|
|
3120
3134
|
const template = this.getTemplate(subTemplate);
|
|
@@ -3196,14 +3210,14 @@ let tokenizeString = function (expr) {
|
|
|
3196
3210
|
i++;
|
|
3197
3211
|
cur = expr[i];
|
|
3198
3212
|
if (!cur) {
|
|
3199
|
-
throw new
|
|
3213
|
+
throw new OwlError("Invalid expression");
|
|
3200
3214
|
}
|
|
3201
3215
|
s += cur;
|
|
3202
3216
|
}
|
|
3203
3217
|
i++;
|
|
3204
3218
|
}
|
|
3205
3219
|
if (expr[i] !== start) {
|
|
3206
|
-
throw new
|
|
3220
|
+
throw new OwlError("Invalid expression");
|
|
3207
3221
|
}
|
|
3208
3222
|
s += start;
|
|
3209
3223
|
if (start === "`") {
|
|
@@ -3310,7 +3324,7 @@ function tokenize(expr) {
|
|
|
3310
3324
|
error = e; // Silence all errors and throw a generic error below
|
|
3311
3325
|
}
|
|
3312
3326
|
if (current.length || error) {
|
|
3313
|
-
throw new
|
|
3327
|
+
throw new OwlError(`Tokenizer error: could not tokenize \`${expr}\``);
|
|
3314
3328
|
}
|
|
3315
3329
|
return result;
|
|
3316
3330
|
}
|
|
@@ -3861,7 +3875,7 @@ class CodeGenerator {
|
|
|
3861
3875
|
.slice(1)
|
|
3862
3876
|
.map((m) => {
|
|
3863
3877
|
if (!MODS.has(m)) {
|
|
3864
|
-
throw new
|
|
3878
|
+
throw new OwlError(`Unknown event modifier: '${m}'`);
|
|
3865
3879
|
}
|
|
3866
3880
|
return `"${m}"`;
|
|
3867
3881
|
});
|
|
@@ -3907,8 +3921,13 @@ class CodeGenerator {
|
|
|
3907
3921
|
expr = compileExpr(ast.attrs[key]);
|
|
3908
3922
|
if (attrName && isProp(ast.tag, attrName)) {
|
|
3909
3923
|
// we force a new string or new boolean to bypass the equality check in blockdom when patching same value
|
|
3910
|
-
|
|
3911
|
-
|
|
3924
|
+
if (attrName === "value") {
|
|
3925
|
+
// When the expression is falsy, fall back to an empty string
|
|
3926
|
+
expr = `new String((${expr}) || "")`;
|
|
3927
|
+
}
|
|
3928
|
+
else {
|
|
3929
|
+
expr = `new Boolean(${expr})`;
|
|
3930
|
+
}
|
|
3912
3931
|
}
|
|
3913
3932
|
const idx = block.insertData(expr, "attr");
|
|
3914
3933
|
if (key === "t-att") {
|
|
@@ -4182,7 +4201,8 @@ class CodeGenerator {
|
|
|
4182
4201
|
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
|
4183
4202
|
if (this.dev) {
|
|
4184
4203
|
// Throw error on duplicate keys in dev mode
|
|
4185
|
-
this.
|
|
4204
|
+
this.helpers.add("OwlError");
|
|
4205
|
+
this.addLine(`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);
|
|
4186
4206
|
this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`);
|
|
4187
4207
|
}
|
|
4188
4208
|
let id;
|
|
@@ -4396,7 +4416,7 @@ class CodeGenerator {
|
|
|
4396
4416
|
value = `bind(ctx, ${value || undefined})`;
|
|
4397
4417
|
}
|
|
4398
4418
|
else {
|
|
4399
|
-
throw new
|
|
4419
|
+
throw new OwlError("Invalid prop suffix");
|
|
4400
4420
|
}
|
|
4401
4421
|
}
|
|
4402
4422
|
name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
|
|
@@ -4589,9 +4609,6 @@ class CodeGenerator {
|
|
|
4589
4609
|
}
|
|
4590
4610
|
}
|
|
4591
4611
|
|
|
4592
|
-
// -----------------------------------------------------------------------------
|
|
4593
|
-
// AST Type definition
|
|
4594
|
-
// -----------------------------------------------------------------------------
|
|
4595
4612
|
// -----------------------------------------------------------------------------
|
|
4596
4613
|
// Parser
|
|
4597
4614
|
// -----------------------------------------------------------------------------
|
|
@@ -4700,7 +4717,7 @@ function parseDOMNode(node, ctx) {
|
|
|
4700
4717
|
return null;
|
|
4701
4718
|
}
|
|
4702
4719
|
if (tagName.startsWith("block-")) {
|
|
4703
|
-
throw new
|
|
4720
|
+
throw new OwlError(`Invalid tag name: '${tagName}'`);
|
|
4704
4721
|
}
|
|
4705
4722
|
ctx = Object.assign({}, ctx);
|
|
4706
4723
|
if (tagName === "pre") {
|
|
@@ -4719,14 +4736,14 @@ function parseDOMNode(node, ctx) {
|
|
|
4719
4736
|
const value = node.getAttribute(attr);
|
|
4720
4737
|
if (attr.startsWith("t-on")) {
|
|
4721
4738
|
if (attr === "t-on") {
|
|
4722
|
-
throw new
|
|
4739
|
+
throw new OwlError("Missing event name with t-on directive");
|
|
4723
4740
|
}
|
|
4724
4741
|
on = on || {};
|
|
4725
4742
|
on[attr.slice(5)] = value;
|
|
4726
4743
|
}
|
|
4727
4744
|
else if (attr.startsWith("t-model")) {
|
|
4728
4745
|
if (!["input", "select", "textarea"].includes(tagName)) {
|
|
4729
|
-
throw new
|
|
4746
|
+
throw new OwlError("The t-model directive only works with <input>, <textarea> and <select>");
|
|
4730
4747
|
}
|
|
4731
4748
|
let baseExpr, expr;
|
|
4732
4749
|
if (hasDotAtTheEnd.test(value)) {
|
|
@@ -4740,7 +4757,7 @@ function parseDOMNode(node, ctx) {
|
|
|
4740
4757
|
expr = value.slice(index + 1, -1);
|
|
4741
4758
|
}
|
|
4742
4759
|
else {
|
|
4743
|
-
throw new
|
|
4760
|
+
throw new OwlError(`Invalid t-model expression: "${value}" (it should be assignable)`);
|
|
4744
4761
|
}
|
|
4745
4762
|
const typeAttr = node.getAttribute("type");
|
|
4746
4763
|
const isInput = tagName === "input";
|
|
@@ -4770,11 +4787,11 @@ function parseDOMNode(node, ctx) {
|
|
|
4770
4787
|
}
|
|
4771
4788
|
}
|
|
4772
4789
|
else if (attr.startsWith("block-")) {
|
|
4773
|
-
throw new
|
|
4790
|
+
throw new OwlError(`Invalid attribute: '${attr}'`);
|
|
4774
4791
|
}
|
|
4775
4792
|
else if (attr !== "t-name") {
|
|
4776
4793
|
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
|
4777
|
-
throw new
|
|
4794
|
+
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
|
4778
4795
|
}
|
|
4779
4796
|
const tModel = ctx.tModelInfo;
|
|
4780
4797
|
if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
|
|
@@ -4825,7 +4842,7 @@ function parseTEscNode(node, ctx) {
|
|
|
4825
4842
|
};
|
|
4826
4843
|
}
|
|
4827
4844
|
if (ast.type === 11 /* TComponent */) {
|
|
4828
|
-
throw new
|
|
4845
|
+
throw new OwlError("t-esc is not supported on Component nodes");
|
|
4829
4846
|
}
|
|
4830
4847
|
return tesc;
|
|
4831
4848
|
}
|
|
@@ -4873,7 +4890,7 @@ function parseTForEach(node, ctx) {
|
|
|
4873
4890
|
node.removeAttribute("t-as");
|
|
4874
4891
|
const key = node.getAttribute("t-key");
|
|
4875
4892
|
if (!key) {
|
|
4876
|
-
throw new
|
|
4893
|
+
throw new OwlError(`"Directive t-foreach should always be used with a t-key!" (expression: t-foreach="${collection}" t-as="${elem}")`);
|
|
4877
4894
|
}
|
|
4878
4895
|
node.removeAttribute("t-key");
|
|
4879
4896
|
const memo = node.getAttribute("t-memo") || "";
|
|
@@ -5033,7 +5050,7 @@ function parseComponent(node, ctx) {
|
|
|
5033
5050
|
const firstLetter = name[0];
|
|
5034
5051
|
let isDynamic = node.hasAttribute("t-component");
|
|
5035
5052
|
if (isDynamic && name !== "t") {
|
|
5036
|
-
throw new
|
|
5053
|
+
throw new OwlError(`Directive 't-component' can only be used on <t> nodes (used on a <${name}>)`);
|
|
5037
5054
|
}
|
|
5038
5055
|
if (!(firstLetter === firstLetter.toUpperCase() || isDynamic)) {
|
|
5039
5056
|
return null;
|
|
@@ -5057,7 +5074,7 @@ function parseComponent(node, ctx) {
|
|
|
5057
5074
|
}
|
|
5058
5075
|
else {
|
|
5059
5076
|
const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
|
|
5060
|
-
throw new
|
|
5077
|
+
throw new OwlError(message || `unsupported directive on Component: ${name}`);
|
|
5061
5078
|
}
|
|
5062
5079
|
}
|
|
5063
5080
|
else {
|
|
@@ -5072,7 +5089,7 @@ function parseComponent(node, ctx) {
|
|
|
5072
5089
|
const slotNodes = Array.from(clone.querySelectorAll("[t-set-slot]"));
|
|
5073
5090
|
for (let slotNode of slotNodes) {
|
|
5074
5091
|
if (slotNode.tagName !== "t") {
|
|
5075
|
-
throw new
|
|
5092
|
+
throw new OwlError(`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`);
|
|
5076
5093
|
}
|
|
5077
5094
|
const name = slotNode.getAttribute("t-set-slot");
|
|
5078
5095
|
// check if this is defined in a sub component (in which case it should
|
|
@@ -5237,25 +5254,25 @@ function normalizeTIf(el) {
|
|
|
5237
5254
|
let nattr = (name) => +!!node.getAttribute(name);
|
|
5238
5255
|
if (prevElem && (pattr("t-if") || pattr("t-elif"))) {
|
|
5239
5256
|
if (pattr("t-foreach")) {
|
|
5240
|
-
throw new
|
|
5257
|
+
throw new OwlError("t-if cannot stay at the same level as t-foreach when using t-elif or t-else");
|
|
5241
5258
|
}
|
|
5242
5259
|
if (["t-if", "t-elif", "t-else"].map(nattr).reduce(function (a, b) {
|
|
5243
5260
|
return a + b;
|
|
5244
5261
|
}) > 1) {
|
|
5245
|
-
throw new
|
|
5262
|
+
throw new OwlError("Only one conditional branching directive is allowed per node");
|
|
5246
5263
|
}
|
|
5247
5264
|
// All text (with only spaces) and comment nodes (nodeType 8) between
|
|
5248
5265
|
// branch nodes are removed
|
|
5249
5266
|
let textNode;
|
|
5250
5267
|
while ((textNode = node.previousSibling) !== prevElem) {
|
|
5251
5268
|
if (textNode.nodeValue.trim().length && textNode.nodeType !== 8) {
|
|
5252
|
-
throw new
|
|
5269
|
+
throw new OwlError("text is not allowed between branching directives");
|
|
5253
5270
|
}
|
|
5254
5271
|
textNode.remove();
|
|
5255
5272
|
}
|
|
5256
5273
|
}
|
|
5257
5274
|
else {
|
|
5258
|
-
throw new
|
|
5275
|
+
throw new OwlError("t-elif and t-else directives must be preceded by a t-if or t-elif directive");
|
|
5259
5276
|
}
|
|
5260
5277
|
}
|
|
5261
5278
|
}
|
|
@@ -5271,7 +5288,7 @@ function normalizeTEsc(el) {
|
|
|
5271
5288
|
const elements = [...el.querySelectorAll("[t-esc]")].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component"));
|
|
5272
5289
|
for (const el of elements) {
|
|
5273
5290
|
if (el.childNodes.length) {
|
|
5274
|
-
throw new
|
|
5291
|
+
throw new OwlError("Cannot have t-esc on a component that already has content");
|
|
5275
5292
|
}
|
|
5276
5293
|
const value = el.getAttribute("t-esc");
|
|
5277
5294
|
el.removeAttribute("t-esc");
|
|
@@ -5323,7 +5340,7 @@ function parseXML(xml) {
|
|
|
5323
5340
|
}
|
|
5324
5341
|
}
|
|
5325
5342
|
}
|
|
5326
|
-
throw new
|
|
5343
|
+
throw new OwlError(msg);
|
|
5327
5344
|
}
|
|
5328
5345
|
return doc;
|
|
5329
5346
|
}
|
|
@@ -5377,7 +5394,7 @@ const mainEventHandler = (data, ev, currentTarget) => {
|
|
|
5377
5394
|
if (Object.hasOwnProperty.call(data, 0)) {
|
|
5378
5395
|
const handler = data[0];
|
|
5379
5396
|
if (typeof handler !== "function") {
|
|
5380
|
-
throw new
|
|
5397
|
+
throw new OwlError(`Invalid handler (expected a function, received: '${handler}')`);
|
|
5381
5398
|
}
|
|
5382
5399
|
let node = data[1] ? data[1].__owl__ : null;
|
|
5383
5400
|
if (node ? node.status === 1 /* MOUNTED */ : true) {
|
|
@@ -5561,10 +5578,10 @@ class App extends TemplateSet {
|
|
|
5561
5578
|
if (isStatic) {
|
|
5562
5579
|
C = parent.constructor.components[name];
|
|
5563
5580
|
if (!C) {
|
|
5564
|
-
throw new
|
|
5581
|
+
throw new OwlError(`Cannot find the definition of component "${name}"`);
|
|
5565
5582
|
}
|
|
5566
5583
|
else if (!(C.prototype instanceof Component)) {
|
|
5567
|
-
throw new
|
|
5584
|
+
throw new OwlError(`"${name}" is not a Component. It must inherit from the Component class`);
|
|
5568
5585
|
}
|
|
5569
5586
|
}
|
|
5570
5587
|
node = new ComponentNode(C, props, this, ctx, key);
|
|
@@ -5720,10 +5737,10 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
|
|
|
5720
5737
|
});
|
|
5721
5738
|
};
|
|
5722
5739
|
|
|
5723
|
-
export { App, Component, EventBus, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, whenReady, xml };
|
|
5740
|
+
export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, whenReady, xml };
|
|
5724
5741
|
|
|
5725
5742
|
|
|
5726
|
-
__info__.version = '2.0.0-beta-
|
|
5727
|
-
__info__.date = '2022-
|
|
5728
|
-
__info__.hash = '
|
|
5743
|
+
__info__.version = '2.0.0-beta-17';
|
|
5744
|
+
__info__.date = '2022-09-01T13:41:44.572Z';
|
|
5745
|
+
__info__.hash = '9cb74d6';
|
|
5729
5746
|
__info__.url = 'https://github.com/odoo/owl';
|