@odoo/owl 2.0.9 → 2.1.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/README.md +22 -1
- package/dist/owl-devtools.zip +0 -0
- package/dist/owl.cjs.js +115 -86
- package/dist/owl.es.js +115 -87
- package/dist/owl.iife.js +115 -86
- package/dist/owl.iife.min.js +1 -1
- package/dist/types/owl.d.ts +11 -8
- package/dist/types/runtime/app.d.ts +2 -2
- package/dist/types/runtime/component_node.d.ts +1 -0
- package/dist/types/runtime/index.d.ts +1 -1
- package/dist/types/runtime/lifecycle_hooks.d.ts +3 -3
- package/dist/types/runtime/utils.d.ts +6 -1
- package/dist/types/runtime/validation.d.ts +2 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -113,6 +113,7 @@ Are you new to Owl? This is the place to start!
|
|
|
113
113
|
- [Why did Odoo build Owl?](doc/miscellaneous/why_owl.md)
|
|
114
114
|
- [Changelog (from owl 1.x to 2.x)](CHANGELOG.md)
|
|
115
115
|
- [Notes on compiled templates](doc/miscellaneous/compiled_template.md)
|
|
116
|
+
- [Owl devtools extension](doc/tools/devtools.md)
|
|
116
117
|
|
|
117
118
|
## Installing Owl
|
|
118
119
|
|
|
@@ -121,8 +122,28 @@ Owl is available on `npm` and can be installed with the following command:
|
|
|
121
122
|
```
|
|
122
123
|
npm install @odoo/owl
|
|
123
124
|
```
|
|
124
|
-
|
|
125
125
|
If you want to use a simple `<script>` tag, the last release can be downloaded here:
|
|
126
126
|
|
|
127
127
|
- [owl](https://github.com/odoo/owl/releases/latest)
|
|
128
128
|
|
|
129
|
+
## Installing Owl devtools
|
|
130
|
+
|
|
131
|
+
The Owl devtools browser extension is also available in the [release](https://github.com/odoo/owl/releases/latest):
|
|
132
|
+
Unzip the owl-devtools.zip file and follow the instructions depending on your browser:
|
|
133
|
+
|
|
134
|
+
### Chrome
|
|
135
|
+
|
|
136
|
+
Go to your chrome extensions admin panel, activate developer mode and click on `Load unpacked`.
|
|
137
|
+
Select the devtools-chrome folder and that's it, your extension is active!
|
|
138
|
+
There is a convenient refresh button on the extension card (still on the same admin page) to update your code.
|
|
139
|
+
Do note that if you got some problems, you may need to completly remove and reload the extension to completly refresh the extension.
|
|
140
|
+
|
|
141
|
+
### Firefox
|
|
142
|
+
Go to the address about:debugging#/runtime/this-firefox and click on `Load temporary Add-on...`.
|
|
143
|
+
Select any file in the devtools-firefox folder and that's it, your extension is active!
|
|
144
|
+
Here, you can use the reload button to refresh the extension.
|
|
145
|
+
|
|
146
|
+
Note that you may have to open another window or reload your tab to see the extension working.
|
|
147
|
+
Also note that the extension will only be active on pages that have a sufficient version of owl.
|
|
148
|
+
|
|
149
|
+
|
|
Binary file
|
package/dist/owl.cjs.js
CHANGED
|
@@ -282,6 +282,96 @@ function updateClass(val, oldVal) {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Creates a batched version of a callback so that all calls to it in the same
|
|
287
|
+
* microtick will only call the original callback once.
|
|
288
|
+
*
|
|
289
|
+
* @param callback the callback to batch
|
|
290
|
+
* @returns a batched version of the original callback
|
|
291
|
+
*/
|
|
292
|
+
function batched(callback) {
|
|
293
|
+
let called = false;
|
|
294
|
+
return async () => {
|
|
295
|
+
// This await blocks all calls to the callback here, then releases them sequentially
|
|
296
|
+
// in the next microtick. This line decides the granularity of the batch.
|
|
297
|
+
await Promise.resolve();
|
|
298
|
+
if (!called) {
|
|
299
|
+
called = true;
|
|
300
|
+
// wait for all calls in this microtick to fall through before resetting "called"
|
|
301
|
+
// so that only the first call to the batched function calls the original callback.
|
|
302
|
+
// Schedule this before calling the callback so that calls to the batched function
|
|
303
|
+
// within the callback will proceed only after resetting called to false, and have
|
|
304
|
+
// a chance to execute the callback again
|
|
305
|
+
Promise.resolve().then(() => (called = false));
|
|
306
|
+
callback();
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Determine whether the given element is contained in its ownerDocument:
|
|
312
|
+
* either directly or with a shadow root in between.
|
|
313
|
+
*/
|
|
314
|
+
function inOwnerDocument(el) {
|
|
315
|
+
if (!el) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
if (el.ownerDocument.contains(el)) {
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
const rootNode = el.getRootNode();
|
|
322
|
+
return rootNode instanceof ShadowRoot && el.ownerDocument.contains(rootNode.host);
|
|
323
|
+
}
|
|
324
|
+
function validateTarget(target) {
|
|
325
|
+
// Get the document and HTMLElement corresponding to the target to allow mounting in iframes
|
|
326
|
+
const document = target && target.ownerDocument;
|
|
327
|
+
if (document) {
|
|
328
|
+
const HTMLElement = document.defaultView.HTMLElement;
|
|
329
|
+
if (target instanceof HTMLElement || target instanceof ShadowRoot) {
|
|
330
|
+
if (!document.body.contains(target instanceof HTMLElement ? target : target.host)) {
|
|
331
|
+
throw new OwlError("Cannot mount a component on a detached dom node");
|
|
332
|
+
}
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
|
|
337
|
+
}
|
|
338
|
+
class EventBus extends EventTarget {
|
|
339
|
+
trigger(name, payload) {
|
|
340
|
+
this.dispatchEvent(new CustomEvent(name, { detail: payload }));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function whenReady(fn) {
|
|
344
|
+
return new Promise(function (resolve) {
|
|
345
|
+
if (document.readyState !== "loading") {
|
|
346
|
+
resolve(true);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
document.addEventListener("DOMContentLoaded", resolve, false);
|
|
350
|
+
}
|
|
351
|
+
}).then(fn || function () { });
|
|
352
|
+
}
|
|
353
|
+
async function loadFile(url) {
|
|
354
|
+
const result = await fetch(url);
|
|
355
|
+
if (!result.ok) {
|
|
356
|
+
throw new OwlError("Error while fetching xml templates");
|
|
357
|
+
}
|
|
358
|
+
return await result.text();
|
|
359
|
+
}
|
|
360
|
+
/*
|
|
361
|
+
* This class just transports the fact that a string is safe
|
|
362
|
+
* to be injected as HTML. Overriding a JS primitive is quite painful though
|
|
363
|
+
* so we need to redfine toString and valueOf.
|
|
364
|
+
*/
|
|
365
|
+
class Markup extends String {
|
|
366
|
+
}
|
|
367
|
+
/*
|
|
368
|
+
* Marks a value as safe, that is, a value that can be injected as HTML directly.
|
|
369
|
+
* It should be used to wrap the value passed to a t-out directive to allow a raw rendering.
|
|
370
|
+
*/
|
|
371
|
+
function markup(value) {
|
|
372
|
+
return new Markup(value);
|
|
373
|
+
}
|
|
374
|
+
|
|
285
375
|
function createEventHandler(rawEvent) {
|
|
286
376
|
const eventName = rawEvent.split(".")[0];
|
|
287
377
|
const capture = rawEvent.includes(".capture");
|
|
@@ -301,7 +391,7 @@ function createElementHandler(evName, capture = false) {
|
|
|
301
391
|
}
|
|
302
392
|
function listener(ev) {
|
|
303
393
|
const currentTarget = ev.currentTarget;
|
|
304
|
-
if (!currentTarget || !
|
|
394
|
+
if (!currentTarget || !inOwnerDocument(currentTarget))
|
|
305
395
|
return;
|
|
306
396
|
const data = currentTarget[eventKey];
|
|
307
397
|
if (!data)
|
|
@@ -2166,82 +2256,6 @@ function collectionsProxyHandler(target, callback, targetRawType) {
|
|
|
2166
2256
|
});
|
|
2167
2257
|
}
|
|
2168
2258
|
|
|
2169
|
-
/**
|
|
2170
|
-
* Creates a batched version of a callback so that all calls to it in the same
|
|
2171
|
-
* microtick will only call the original callback once.
|
|
2172
|
-
*
|
|
2173
|
-
* @param callback the callback to batch
|
|
2174
|
-
* @returns a batched version of the original callback
|
|
2175
|
-
*/
|
|
2176
|
-
function batched(callback) {
|
|
2177
|
-
let called = false;
|
|
2178
|
-
return async () => {
|
|
2179
|
-
// This await blocks all calls to the callback here, then releases them sequentially
|
|
2180
|
-
// in the next microtick. This line decides the granularity of the batch.
|
|
2181
|
-
await Promise.resolve();
|
|
2182
|
-
if (!called) {
|
|
2183
|
-
called = true;
|
|
2184
|
-
// wait for all calls in this microtick to fall through before resetting "called"
|
|
2185
|
-
// so that only the first call to the batched function calls the original callback.
|
|
2186
|
-
// Schedule this before calling the callback so that calls to the batched function
|
|
2187
|
-
// within the callback will proceed only after resetting called to false, and have
|
|
2188
|
-
// a chance to execute the callback again
|
|
2189
|
-
Promise.resolve().then(() => (called = false));
|
|
2190
|
-
callback();
|
|
2191
|
-
}
|
|
2192
|
-
};
|
|
2193
|
-
}
|
|
2194
|
-
function validateTarget(target) {
|
|
2195
|
-
// Get the document and HTMLElement corresponding to the target to allow mounting in iframes
|
|
2196
|
-
const document = target && target.ownerDocument;
|
|
2197
|
-
if (document) {
|
|
2198
|
-
const HTMLElement = document.defaultView.HTMLElement;
|
|
2199
|
-
if (target instanceof HTMLElement) {
|
|
2200
|
-
if (!document.body.contains(target)) {
|
|
2201
|
-
throw new OwlError("Cannot mount a component on a detached dom node");
|
|
2202
|
-
}
|
|
2203
|
-
return;
|
|
2204
|
-
}
|
|
2205
|
-
}
|
|
2206
|
-
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
|
|
2207
|
-
}
|
|
2208
|
-
class EventBus extends EventTarget {
|
|
2209
|
-
trigger(name, payload) {
|
|
2210
|
-
this.dispatchEvent(new CustomEvent(name, { detail: payload }));
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
|
-
function whenReady(fn) {
|
|
2214
|
-
return new Promise(function (resolve) {
|
|
2215
|
-
if (document.readyState !== "loading") {
|
|
2216
|
-
resolve(true);
|
|
2217
|
-
}
|
|
2218
|
-
else {
|
|
2219
|
-
document.addEventListener("DOMContentLoaded", resolve, false);
|
|
2220
|
-
}
|
|
2221
|
-
}).then(fn || function () { });
|
|
2222
|
-
}
|
|
2223
|
-
async function loadFile(url) {
|
|
2224
|
-
const result = await fetch(url);
|
|
2225
|
-
if (!result.ok) {
|
|
2226
|
-
throw new OwlError("Error while fetching xml templates");
|
|
2227
|
-
}
|
|
2228
|
-
return await result.text();
|
|
2229
|
-
}
|
|
2230
|
-
/*
|
|
2231
|
-
* This class just transports the fact that a string is safe
|
|
2232
|
-
* to be injected as HTML. Overriding a JS primitive is quite painful though
|
|
2233
|
-
* so we need to redfine toString and valueOf.
|
|
2234
|
-
*/
|
|
2235
|
-
class Markup extends String {
|
|
2236
|
-
}
|
|
2237
|
-
/*
|
|
2238
|
-
* Marks a value as safe, that is, a value that can be injected as HTML directly.
|
|
2239
|
-
* It should be used to wrap the value passed to a t-out directive to allow a raw rendering.
|
|
2240
|
-
*/
|
|
2241
|
-
function markup(value) {
|
|
2242
|
-
return new Markup(value);
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
2259
|
let currentNode = null;
|
|
2246
2260
|
function getCurrent() {
|
|
2247
2261
|
if (!currentNode) {
|
|
@@ -2293,6 +2307,7 @@ class ComponentNode {
|
|
|
2293
2307
|
this.bdom = null;
|
|
2294
2308
|
this.status = 0 /* NEW */;
|
|
2295
2309
|
this.forceNextRender = false;
|
|
2310
|
+
this.nextProps = null;
|
|
2296
2311
|
this.children = Object.create(null);
|
|
2297
2312
|
this.refs = {};
|
|
2298
2313
|
this.willStart = [];
|
|
@@ -2422,7 +2437,7 @@ class ComponentNode {
|
|
|
2422
2437
|
this.status = 2 /* DESTROYED */;
|
|
2423
2438
|
}
|
|
2424
2439
|
async updateAndRender(props, parentFiber) {
|
|
2425
|
-
|
|
2440
|
+
this.nextProps = props;
|
|
2426
2441
|
props = Object.assign({}, props);
|
|
2427
2442
|
// update
|
|
2428
2443
|
const fiber = makeChildFiber(this, parentFiber);
|
|
@@ -2446,7 +2461,6 @@ class ComponentNode {
|
|
|
2446
2461
|
return;
|
|
2447
2462
|
}
|
|
2448
2463
|
component.props = props;
|
|
2449
|
-
this.props = rawProps;
|
|
2450
2464
|
fiber.render();
|
|
2451
2465
|
const parentRoot = parentFiber.root;
|
|
2452
2466
|
if (this.willPatch.length) {
|
|
@@ -2521,6 +2535,7 @@ class ComponentNode {
|
|
|
2521
2535
|
// by the component will be patched independently in the appropriate
|
|
2522
2536
|
// fiber.complete
|
|
2523
2537
|
this._patch();
|
|
2538
|
+
this.props = this.nextProps;
|
|
2524
2539
|
}
|
|
2525
2540
|
}
|
|
2526
2541
|
_patch() {
|
|
@@ -2871,14 +2886,27 @@ function validateType(key, value, descr) {
|
|
|
2871
2886
|
if ("element" in descr) {
|
|
2872
2887
|
result = validateArrayType(key, value, descr.element);
|
|
2873
2888
|
}
|
|
2874
|
-
else if ("shape" in descr
|
|
2889
|
+
else if ("shape" in descr) {
|
|
2875
2890
|
if (typeof value !== "object" || Array.isArray(value)) {
|
|
2876
2891
|
result = `'${key}' is not an object`;
|
|
2877
2892
|
}
|
|
2878
2893
|
else {
|
|
2879
2894
|
const errors = validateSchema(value, descr.shape);
|
|
2880
2895
|
if (errors.length) {
|
|
2881
|
-
result = `'${key}'
|
|
2896
|
+
result = `'${key}' doesn't have the correct shape (${errors.join(", ")})`;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
else if ("values" in descr) {
|
|
2901
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
2902
|
+
result = `'${key}' is not an object`;
|
|
2903
|
+
}
|
|
2904
|
+
else {
|
|
2905
|
+
const errors = Object.entries(value)
|
|
2906
|
+
.map(([key, value]) => validateType(key, value, descr.values))
|
|
2907
|
+
.filter(Boolean);
|
|
2908
|
+
if (errors.length) {
|
|
2909
|
+
result = `some of the values in '${key}' are invalid (${errors.join(", ")})`;
|
|
2882
2910
|
}
|
|
2883
2911
|
}
|
|
2884
2912
|
}
|
|
@@ -5481,8 +5509,8 @@ function compile(template, options = {}) {
|
|
|
5481
5509
|
return new Function("app, bdom, helpers", code);
|
|
5482
5510
|
}
|
|
5483
5511
|
|
|
5484
|
-
// do not modify manually. This
|
|
5485
|
-
const version = "2.
|
|
5512
|
+
// do not modify manually. This file is generated by the release script.
|
|
5513
|
+
const version = "2.1.1";
|
|
5486
5514
|
|
|
5487
5515
|
// -----------------------------------------------------------------------------
|
|
5488
5516
|
// Scheduler
|
|
@@ -5775,7 +5803,7 @@ function useRef(name) {
|
|
|
5775
5803
|
return {
|
|
5776
5804
|
get el() {
|
|
5777
5805
|
const el = refs[name];
|
|
5778
|
-
return (el
|
|
5806
|
+
return inOwnerDocument(el) ? el : null;
|
|
5779
5807
|
},
|
|
5780
5808
|
};
|
|
5781
5809
|
}
|
|
@@ -5925,10 +5953,11 @@ exports.useRef = useRef;
|
|
|
5925
5953
|
exports.useState = useState;
|
|
5926
5954
|
exports.useSubEnv = useSubEnv;
|
|
5927
5955
|
exports.validate = validate;
|
|
5956
|
+
exports.validateType = validateType;
|
|
5928
5957
|
exports.whenReady = whenReady;
|
|
5929
5958
|
exports.xml = xml;
|
|
5930
5959
|
|
|
5931
5960
|
|
|
5932
|
-
__info__.date = '2023-
|
|
5933
|
-
__info__.hash = '
|
|
5961
|
+
__info__.date = '2023-04-17T09:09:34.568Z';
|
|
5962
|
+
__info__.hash = '4b9e6ba';
|
|
5934
5963
|
__info__.url = 'https://github.com/odoo/owl';
|
package/dist/owl.es.js
CHANGED
|
@@ -278,6 +278,96 @@ function updateClass(val, oldVal) {
|
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Creates a batched version of a callback so that all calls to it in the same
|
|
283
|
+
* microtick will only call the original callback once.
|
|
284
|
+
*
|
|
285
|
+
* @param callback the callback to batch
|
|
286
|
+
* @returns a batched version of the original callback
|
|
287
|
+
*/
|
|
288
|
+
function batched(callback) {
|
|
289
|
+
let called = false;
|
|
290
|
+
return async () => {
|
|
291
|
+
// This await blocks all calls to the callback here, then releases them sequentially
|
|
292
|
+
// in the next microtick. This line decides the granularity of the batch.
|
|
293
|
+
await Promise.resolve();
|
|
294
|
+
if (!called) {
|
|
295
|
+
called = true;
|
|
296
|
+
// wait for all calls in this microtick to fall through before resetting "called"
|
|
297
|
+
// so that only the first call to the batched function calls the original callback.
|
|
298
|
+
// Schedule this before calling the callback so that calls to the batched function
|
|
299
|
+
// within the callback will proceed only after resetting called to false, and have
|
|
300
|
+
// a chance to execute the callback again
|
|
301
|
+
Promise.resolve().then(() => (called = false));
|
|
302
|
+
callback();
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Determine whether the given element is contained in its ownerDocument:
|
|
308
|
+
* either directly or with a shadow root in between.
|
|
309
|
+
*/
|
|
310
|
+
function inOwnerDocument(el) {
|
|
311
|
+
if (!el) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
if (el.ownerDocument.contains(el)) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
const rootNode = el.getRootNode();
|
|
318
|
+
return rootNode instanceof ShadowRoot && el.ownerDocument.contains(rootNode.host);
|
|
319
|
+
}
|
|
320
|
+
function validateTarget(target) {
|
|
321
|
+
// Get the document and HTMLElement corresponding to the target to allow mounting in iframes
|
|
322
|
+
const document = target && target.ownerDocument;
|
|
323
|
+
if (document) {
|
|
324
|
+
const HTMLElement = document.defaultView.HTMLElement;
|
|
325
|
+
if (target instanceof HTMLElement || target instanceof ShadowRoot) {
|
|
326
|
+
if (!document.body.contains(target instanceof HTMLElement ? target : target.host)) {
|
|
327
|
+
throw new OwlError("Cannot mount a component on a detached dom node");
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
|
|
333
|
+
}
|
|
334
|
+
class EventBus extends EventTarget {
|
|
335
|
+
trigger(name, payload) {
|
|
336
|
+
this.dispatchEvent(new CustomEvent(name, { detail: payload }));
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function whenReady(fn) {
|
|
340
|
+
return new Promise(function (resolve) {
|
|
341
|
+
if (document.readyState !== "loading") {
|
|
342
|
+
resolve(true);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
document.addEventListener("DOMContentLoaded", resolve, false);
|
|
346
|
+
}
|
|
347
|
+
}).then(fn || function () { });
|
|
348
|
+
}
|
|
349
|
+
async function loadFile(url) {
|
|
350
|
+
const result = await fetch(url);
|
|
351
|
+
if (!result.ok) {
|
|
352
|
+
throw new OwlError("Error while fetching xml templates");
|
|
353
|
+
}
|
|
354
|
+
return await result.text();
|
|
355
|
+
}
|
|
356
|
+
/*
|
|
357
|
+
* This class just transports the fact that a string is safe
|
|
358
|
+
* to be injected as HTML. Overriding a JS primitive is quite painful though
|
|
359
|
+
* so we need to redfine toString and valueOf.
|
|
360
|
+
*/
|
|
361
|
+
class Markup extends String {
|
|
362
|
+
}
|
|
363
|
+
/*
|
|
364
|
+
* Marks a value as safe, that is, a value that can be injected as HTML directly.
|
|
365
|
+
* It should be used to wrap the value passed to a t-out directive to allow a raw rendering.
|
|
366
|
+
*/
|
|
367
|
+
function markup(value) {
|
|
368
|
+
return new Markup(value);
|
|
369
|
+
}
|
|
370
|
+
|
|
281
371
|
function createEventHandler(rawEvent) {
|
|
282
372
|
const eventName = rawEvent.split(".")[0];
|
|
283
373
|
const capture = rawEvent.includes(".capture");
|
|
@@ -297,7 +387,7 @@ function createElementHandler(evName, capture = false) {
|
|
|
297
387
|
}
|
|
298
388
|
function listener(ev) {
|
|
299
389
|
const currentTarget = ev.currentTarget;
|
|
300
|
-
if (!currentTarget || !
|
|
390
|
+
if (!currentTarget || !inOwnerDocument(currentTarget))
|
|
301
391
|
return;
|
|
302
392
|
const data = currentTarget[eventKey];
|
|
303
393
|
if (!data)
|
|
@@ -2162,82 +2252,6 @@ function collectionsProxyHandler(target, callback, targetRawType) {
|
|
|
2162
2252
|
});
|
|
2163
2253
|
}
|
|
2164
2254
|
|
|
2165
|
-
/**
|
|
2166
|
-
* Creates a batched version of a callback so that all calls to it in the same
|
|
2167
|
-
* microtick will only call the original callback once.
|
|
2168
|
-
*
|
|
2169
|
-
* @param callback the callback to batch
|
|
2170
|
-
* @returns a batched version of the original callback
|
|
2171
|
-
*/
|
|
2172
|
-
function batched(callback) {
|
|
2173
|
-
let called = false;
|
|
2174
|
-
return async () => {
|
|
2175
|
-
// This await blocks all calls to the callback here, then releases them sequentially
|
|
2176
|
-
// in the next microtick. This line decides the granularity of the batch.
|
|
2177
|
-
await Promise.resolve();
|
|
2178
|
-
if (!called) {
|
|
2179
|
-
called = true;
|
|
2180
|
-
// wait for all calls in this microtick to fall through before resetting "called"
|
|
2181
|
-
// so that only the first call to the batched function calls the original callback.
|
|
2182
|
-
// Schedule this before calling the callback so that calls to the batched function
|
|
2183
|
-
// within the callback will proceed only after resetting called to false, and have
|
|
2184
|
-
// a chance to execute the callback again
|
|
2185
|
-
Promise.resolve().then(() => (called = false));
|
|
2186
|
-
callback();
|
|
2187
|
-
}
|
|
2188
|
-
};
|
|
2189
|
-
}
|
|
2190
|
-
function validateTarget(target) {
|
|
2191
|
-
// Get the document and HTMLElement corresponding to the target to allow mounting in iframes
|
|
2192
|
-
const document = target && target.ownerDocument;
|
|
2193
|
-
if (document) {
|
|
2194
|
-
const HTMLElement = document.defaultView.HTMLElement;
|
|
2195
|
-
if (target instanceof HTMLElement) {
|
|
2196
|
-
if (!document.body.contains(target)) {
|
|
2197
|
-
throw new OwlError("Cannot mount a component on a detached dom node");
|
|
2198
|
-
}
|
|
2199
|
-
return;
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
|
|
2203
|
-
}
|
|
2204
|
-
class EventBus extends EventTarget {
|
|
2205
|
-
trigger(name, payload) {
|
|
2206
|
-
this.dispatchEvent(new CustomEvent(name, { detail: payload }));
|
|
2207
|
-
}
|
|
2208
|
-
}
|
|
2209
|
-
function whenReady(fn) {
|
|
2210
|
-
return new Promise(function (resolve) {
|
|
2211
|
-
if (document.readyState !== "loading") {
|
|
2212
|
-
resolve(true);
|
|
2213
|
-
}
|
|
2214
|
-
else {
|
|
2215
|
-
document.addEventListener("DOMContentLoaded", resolve, false);
|
|
2216
|
-
}
|
|
2217
|
-
}).then(fn || function () { });
|
|
2218
|
-
}
|
|
2219
|
-
async function loadFile(url) {
|
|
2220
|
-
const result = await fetch(url);
|
|
2221
|
-
if (!result.ok) {
|
|
2222
|
-
throw new OwlError("Error while fetching xml templates");
|
|
2223
|
-
}
|
|
2224
|
-
return await result.text();
|
|
2225
|
-
}
|
|
2226
|
-
/*
|
|
2227
|
-
* This class just transports the fact that a string is safe
|
|
2228
|
-
* to be injected as HTML. Overriding a JS primitive is quite painful though
|
|
2229
|
-
* so we need to redfine toString and valueOf.
|
|
2230
|
-
*/
|
|
2231
|
-
class Markup extends String {
|
|
2232
|
-
}
|
|
2233
|
-
/*
|
|
2234
|
-
* Marks a value as safe, that is, a value that can be injected as HTML directly.
|
|
2235
|
-
* It should be used to wrap the value passed to a t-out directive to allow a raw rendering.
|
|
2236
|
-
*/
|
|
2237
|
-
function markup(value) {
|
|
2238
|
-
return new Markup(value);
|
|
2239
|
-
}
|
|
2240
|
-
|
|
2241
2255
|
let currentNode = null;
|
|
2242
2256
|
function getCurrent() {
|
|
2243
2257
|
if (!currentNode) {
|
|
@@ -2289,6 +2303,7 @@ class ComponentNode {
|
|
|
2289
2303
|
this.bdom = null;
|
|
2290
2304
|
this.status = 0 /* NEW */;
|
|
2291
2305
|
this.forceNextRender = false;
|
|
2306
|
+
this.nextProps = null;
|
|
2292
2307
|
this.children = Object.create(null);
|
|
2293
2308
|
this.refs = {};
|
|
2294
2309
|
this.willStart = [];
|
|
@@ -2418,7 +2433,7 @@ class ComponentNode {
|
|
|
2418
2433
|
this.status = 2 /* DESTROYED */;
|
|
2419
2434
|
}
|
|
2420
2435
|
async updateAndRender(props, parentFiber) {
|
|
2421
|
-
|
|
2436
|
+
this.nextProps = props;
|
|
2422
2437
|
props = Object.assign({}, props);
|
|
2423
2438
|
// update
|
|
2424
2439
|
const fiber = makeChildFiber(this, parentFiber);
|
|
@@ -2442,7 +2457,6 @@ class ComponentNode {
|
|
|
2442
2457
|
return;
|
|
2443
2458
|
}
|
|
2444
2459
|
component.props = props;
|
|
2445
|
-
this.props = rawProps;
|
|
2446
2460
|
fiber.render();
|
|
2447
2461
|
const parentRoot = parentFiber.root;
|
|
2448
2462
|
if (this.willPatch.length) {
|
|
@@ -2517,6 +2531,7 @@ class ComponentNode {
|
|
|
2517
2531
|
// by the component will be patched independently in the appropriate
|
|
2518
2532
|
// fiber.complete
|
|
2519
2533
|
this._patch();
|
|
2534
|
+
this.props = this.nextProps;
|
|
2520
2535
|
}
|
|
2521
2536
|
}
|
|
2522
2537
|
_patch() {
|
|
@@ -2867,14 +2882,27 @@ function validateType(key, value, descr) {
|
|
|
2867
2882
|
if ("element" in descr) {
|
|
2868
2883
|
result = validateArrayType(key, value, descr.element);
|
|
2869
2884
|
}
|
|
2870
|
-
else if ("shape" in descr
|
|
2885
|
+
else if ("shape" in descr) {
|
|
2871
2886
|
if (typeof value !== "object" || Array.isArray(value)) {
|
|
2872
2887
|
result = `'${key}' is not an object`;
|
|
2873
2888
|
}
|
|
2874
2889
|
else {
|
|
2875
2890
|
const errors = validateSchema(value, descr.shape);
|
|
2876
2891
|
if (errors.length) {
|
|
2877
|
-
result = `'${key}'
|
|
2892
|
+
result = `'${key}' doesn't have the correct shape (${errors.join(", ")})`;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
else if ("values" in descr) {
|
|
2897
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
2898
|
+
result = `'${key}' is not an object`;
|
|
2899
|
+
}
|
|
2900
|
+
else {
|
|
2901
|
+
const errors = Object.entries(value)
|
|
2902
|
+
.map(([key, value]) => validateType(key, value, descr.values))
|
|
2903
|
+
.filter(Boolean);
|
|
2904
|
+
if (errors.length) {
|
|
2905
|
+
result = `some of the values in '${key}' are invalid (${errors.join(", ")})`;
|
|
2878
2906
|
}
|
|
2879
2907
|
}
|
|
2880
2908
|
}
|
|
@@ -5477,8 +5505,8 @@ function compile(template, options = {}) {
|
|
|
5477
5505
|
return new Function("app, bdom, helpers", code);
|
|
5478
5506
|
}
|
|
5479
5507
|
|
|
5480
|
-
// do not modify manually. This
|
|
5481
|
-
const version = "2.
|
|
5508
|
+
// do not modify manually. This file is generated by the release script.
|
|
5509
|
+
const version = "2.1.1";
|
|
5482
5510
|
|
|
5483
5511
|
// -----------------------------------------------------------------------------
|
|
5484
5512
|
// Scheduler
|
|
@@ -5771,7 +5799,7 @@ function useRef(name) {
|
|
|
5771
5799
|
return {
|
|
5772
5800
|
get el() {
|
|
5773
5801
|
const el = refs[name];
|
|
5774
|
-
return (el
|
|
5802
|
+
return inOwnerDocument(el) ? el : null;
|
|
5775
5803
|
},
|
|
5776
5804
|
};
|
|
5777
5805
|
}
|
|
@@ -5889,9 +5917,9 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
|
|
|
5889
5917
|
});
|
|
5890
5918
|
};
|
|
5891
5919
|
|
|
5892
|
-
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 };
|
|
5920
|
+
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, validateType, whenReady, xml };
|
|
5893
5921
|
|
|
5894
5922
|
|
|
5895
|
-
__info__.date = '2023-
|
|
5896
|
-
__info__.hash = '
|
|
5923
|
+
__info__.date = '2023-04-17T09:09:34.568Z';
|
|
5924
|
+
__info__.hash = '4b9e6ba';
|
|
5897
5925
|
__info__.url = 'https://github.com/odoo/owl';
|