@odoo/owl 2.0.0-beta-10 → 2.0.0-beta-14

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 CHANGED
@@ -171,6 +171,10 @@ function toClassObj(expr) {
171
171
  for (let key in expr) {
172
172
  const value = expr[key];
173
173
  if (value) {
174
+ key = trim.call(key);
175
+ if (!key) {
176
+ continue;
177
+ }
174
178
  const words = split.call(key, wordRegexp);
175
179
  for (let word of words) {
176
180
  result[word] = value;
@@ -214,7 +218,7 @@ function updateClass(val, oldVal) {
214
218
  function makePropSetter(name) {
215
219
  return function setProp(value) {
216
220
  // support 0, fallback to empty string for other falsy values
217
- this[name] = value === 0 ? 0 : value || "";
221
+ this[name] = value === 0 ? 0 : value ? value.valueOf() : "";
218
222
  };
219
223
  }
220
224
  function isProp(tag, key) {
@@ -1487,6 +1491,7 @@ function cancelFibers(fibers) {
1487
1491
  fiber.render = throwOnRender;
1488
1492
  if (node.status === 0 /* NEW */) {
1489
1493
  node.destroy();
1494
+ delete node.parent.children[node.parentKey];
1490
1495
  }
1491
1496
  node.fiber = null;
1492
1497
  if (fiber.bdom) {
@@ -2875,13 +2880,14 @@ function shallowEqual(l1, l2) {
2875
2880
  return true;
2876
2881
  }
2877
2882
  class LazyValue {
2878
- constructor(fn, ctx, node) {
2883
+ constructor(fn, ctx, component, node) {
2879
2884
  this.fn = fn;
2880
2885
  this.ctx = capture(ctx);
2886
+ this.component = component;
2881
2887
  this.node = node;
2882
2888
  }
2883
2889
  evaluate() {
2884
- return this.fn(this.ctx, this.node);
2890
+ return this.fn.call(this.component, this.ctx, this.node);
2885
2891
  }
2886
2892
  toString() {
2887
2893
  return this.evaluate().toString();
@@ -2890,9 +2896,9 @@ class LazyValue {
2890
2896
  /*
2891
2897
  * Safely outputs `value` as a block depending on the nature of `value`
2892
2898
  */
2893
- function safeOutput(value) {
2894
- if (!value) {
2895
- return value;
2899
+ function safeOutput(value, defaultValue) {
2900
+ if (value === undefined) {
2901
+ return defaultValue ? toggler("default", defaultValue) : toggler("undefined", text(""));
2896
2902
  }
2897
2903
  let safeKey;
2898
2904
  let block;
@@ -3178,7 +3184,7 @@ const STATIC_TOKEN_MAP = Object.assign(Object.create(null), {
3178
3184
  });
3179
3185
  // note that the space after typeof is relevant. It makes sure that the formatted
3180
3186
  // expression has a space after typeof. Currently we don't support delete and void
3181
- const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ".split(",");
3187
+ const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ,|,&,^,~".split(",");
3182
3188
  let tokenizeString = function (expr) {
3183
3189
  let s = expr[0];
3184
3190
  let start = s;
@@ -3672,8 +3678,8 @@ class CodeGenerator {
3672
3678
  define(varName, expr) {
3673
3679
  this.addLine(`const ${varName} = ${expr};`);
3674
3680
  }
3675
- insertAnchor(block) {
3676
- const tag = `block-child-${block.children.length}`;
3681
+ insertAnchor(block, index = block.children.length) {
3682
+ const tag = `block-child-${index}`;
3677
3683
  const anchor = xmlDoc.createElement(tag);
3678
3684
  block.insert(anchor);
3679
3685
  }
@@ -3901,13 +3907,18 @@ class CodeGenerator {
3901
3907
  attrs["block-attribute-" + idx] = attrName;
3902
3908
  }
3903
3909
  else if (key.startsWith("t-att")) {
3910
+ attrName = key === "t-att" ? null : key.slice(6);
3904
3911
  expr = compileExpr(ast.attrs[key]);
3912
+ if (attrName && isProp(ast.tag, attrName)) {
3913
+ // we force a new string or new boolean to bypass the equality check in blockdom when patching same value
3914
+ const C = attrName === "value" ? "String" : "Boolean";
3915
+ expr = `new ${C}(${expr})`;
3916
+ }
3905
3917
  const idx = block.insertData(expr, "attr");
3906
3918
  if (key === "t-att") {
3907
3919
  attrs[`block-attributes`] = String(idx);
3908
3920
  }
3909
3921
  else {
3910
- attrName = key.slice(6);
3911
3922
  attrs[`block-attribute-${idx}`] = attrName;
3912
3923
  }
3913
3924
  }
@@ -4065,20 +4076,37 @@ class CodeGenerator {
4065
4076
  this.insertAnchor(block);
4066
4077
  }
4067
4078
  block = this.createBlock(block, "html", ctx);
4068
- this.helpers.add(ast.expr === "0" ? "zero" : "safeOutput");
4069
- let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`;
4070
- if (ast.body) {
4071
- const nextId = BlockDescription.nextBlockId;
4079
+ let blockStr;
4080
+ if (ast.expr === "0") {
4081
+ this.helpers.add("zero");
4082
+ blockStr = `ctx[zero]`;
4083
+ }
4084
+ else if (ast.body) {
4085
+ let bodyValue = null;
4086
+ bodyValue = BlockDescription.nextBlockId;
4072
4087
  const subCtx = createContext(ctx);
4073
4088
  this.compileAST({ type: 3 /* Multi */, content: ast.body }, subCtx);
4074
- this.helpers.add("withDefault");
4075
- expr = `withDefault(${expr}, b${nextId})`;
4089
+ this.helpers.add("safeOutput");
4090
+ blockStr = `safeOutput(${compileExpr(ast.expr)}, b${bodyValue})`;
4091
+ }
4092
+ else {
4093
+ this.helpers.add("safeOutput");
4094
+ blockStr = `safeOutput(${compileExpr(ast.expr)})`;
4095
+ }
4096
+ this.insertBlock(blockStr, block, ctx);
4097
+ }
4098
+ compileTIfBranch(content, block, ctx) {
4099
+ this.target.indentLevel++;
4100
+ let childN = block.children.length;
4101
+ this.compileAST(content, createContext(ctx, { block, index: ctx.index }));
4102
+ if (block.children.length > childN) {
4103
+ // we have some content => need to insert an anchor at correct index
4104
+ this.insertAnchor(block, childN);
4076
4105
  }
4077
- this.insertBlock(`${expr}`, block, ctx);
4106
+ this.target.indentLevel--;
4078
4107
  }
4079
4108
  compileTIf(ast, ctx, nextNode) {
4080
- let { block, forceNewBlock, index } = ctx;
4081
- let currentIndex = index;
4109
+ let { block, forceNewBlock } = ctx;
4082
4110
  const codeIdx = this.target.code.length;
4083
4111
  const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
4084
4112
  if (block) {
@@ -4088,28 +4116,16 @@ class CodeGenerator {
4088
4116
  block = this.createBlock(block, "multi", ctx);
4089
4117
  }
4090
4118
  this.addLine(`if (${compileExpr(ast.condition)}) {`);
4091
- this.target.indentLevel++;
4092
- this.insertAnchor(block);
4093
- const subCtx = createContext(ctx, { block, index: currentIndex });
4094
- this.compileAST(ast.content, subCtx);
4095
- this.target.indentLevel--;
4119
+ this.compileTIfBranch(ast.content, block, ctx);
4096
4120
  if (ast.tElif) {
4097
4121
  for (let clause of ast.tElif) {
4098
4122
  this.addLine(`} else if (${compileExpr(clause.condition)}) {`);
4099
- this.target.indentLevel++;
4100
- this.insertAnchor(block);
4101
- const subCtx = createContext(ctx, { block, index: currentIndex });
4102
- this.compileAST(clause.content, subCtx);
4103
- this.target.indentLevel--;
4123
+ this.compileTIfBranch(clause.content, block, ctx);
4104
4124
  }
4105
4125
  }
4106
4126
  if (ast.tElse) {
4107
4127
  this.addLine(`} else {`);
4108
- this.target.indentLevel++;
4109
- this.insertAnchor(block);
4110
- const subCtx = createContext(ctx, { block, index: currentIndex });
4111
- this.compileAST(ast.tElse, subCtx);
4112
- this.target.indentLevel--;
4128
+ this.compileTIfBranch(ast.tElse, block, ctx);
4113
4129
  }
4114
4130
  this.addLine("}");
4115
4131
  if (isNewBlock) {
@@ -4267,16 +4283,21 @@ class CodeGenerator {
4267
4283
  }
4268
4284
  compileTCall(ast, ctx) {
4269
4285
  let { block, forceNewBlock } = ctx;
4286
+ let ctxVar = ctx.ctxVar || "ctx";
4287
+ if (ast.context) {
4288
+ ctxVar = generateId("ctx");
4289
+ this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
4290
+ }
4270
4291
  if (ast.body) {
4271
- this.addLine(`ctx = Object.create(ctx);`);
4272
- this.addLine(`ctx[isBoundary] = 1;`);
4292
+ this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
4293
+ this.addLine(`${ctxVar}[isBoundary] = 1;`);
4273
4294
  this.helpers.add("isBoundary");
4274
4295
  const nextId = BlockDescription.nextBlockId;
4275
- const subCtx = createContext(ctx, { preventRoot: true });
4296
+ const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
4276
4297
  this.compileAST({ type: 3 /* Multi */, content: ast.body }, subCtx);
4277
4298
  if (nextId !== BlockDescription.nextBlockId) {
4278
4299
  this.helpers.add("zero");
4279
- this.addLine(`ctx[zero] = b${nextId};`);
4300
+ this.addLine(`${ctxVar}[zero] = b${nextId};`);
4280
4301
  }
4281
4302
  }
4282
4303
  const isDynamic = INTERP_REGEXP.test(ast.name);
@@ -4294,7 +4315,7 @@ class CodeGenerator {
4294
4315
  }
4295
4316
  this.define(templateVar, subTemplate);
4296
4317
  block = this.createBlock(block, "multi", ctx);
4297
- this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block, {
4318
+ this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block, {
4298
4319
  ...ctx,
4299
4320
  forceNewBlock: !block,
4300
4321
  });
@@ -4303,13 +4324,13 @@ class CodeGenerator {
4303
4324
  const id = generateId(`callTemplate_`);
4304
4325
  this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
4305
4326
  block = this.createBlock(block, "multi", ctx);
4306
- this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block, {
4327
+ this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block, {
4307
4328
  ...ctx,
4308
4329
  forceNewBlock: !block,
4309
4330
  });
4310
4331
  }
4311
4332
  if (ast.body && !ctx.isLast) {
4312
- this.addLine(`ctx = ctx.__proto__;`);
4333
+ this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
4313
4334
  }
4314
4335
  }
4315
4336
  compileTCallBlock(ast, ctx) {
@@ -4330,7 +4351,7 @@ class CodeGenerator {
4330
4351
  this.helpers.add("LazyValue");
4331
4352
  const bodyAst = { type: 3 /* Multi */, content: ast.body };
4332
4353
  const name = this.compileInNewTarget("value", bodyAst, ctx);
4333
- let value = `new LazyValue(${name}, ctx, node)`;
4354
+ let value = `new LazyValue(${name}, ctx, this, node)`;
4334
4355
  value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
4335
4356
  this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
4336
4357
  }
@@ -4348,7 +4369,7 @@ class CodeGenerator {
4348
4369
  value = expr;
4349
4370
  }
4350
4371
  this.helpers.add("setContextValue");
4351
- this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`);
4372
+ this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
4352
4373
  }
4353
4374
  }
4354
4375
  generateComponentKey() {
@@ -4470,7 +4491,7 @@ class CodeGenerator {
4470
4491
  id,
4471
4492
  expr: `app.createComponent(${ast.isDynamic ? null : expr}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, ${!ast.props && !ast.dynamicProps})`,
4472
4493
  });
4473
- let blockExpr = `${id}(${propString}, ${keyArg}, node, ctx, ${ast.isDynamic ? expr : null})`;
4494
+ let blockExpr = `${id}(${propString}, ${keyArg}, node, this, ${ast.isDynamic ? expr : null})`;
4474
4495
  if (ast.isDynamic) {
4475
4496
  blockExpr = `toggler(${expr}, ${blockExpr})`;
4476
4497
  }
@@ -4903,10 +4924,12 @@ function parseTCall(node, ctx) {
4903
4924
  return null;
4904
4925
  }
4905
4926
  const subTemplate = node.getAttribute("t-call");
4927
+ const context = node.getAttribute("t-call-context");
4906
4928
  node.removeAttribute("t-call");
4929
+ node.removeAttribute("t-call-context");
4907
4930
  if (node.tagName !== "t") {
4908
4931
  const ast = parseNode(node, ctx);
4909
- const tcall = { type: 7 /* TCall */, name: subTemplate, body: null };
4932
+ const tcall = { type: 7 /* TCall */, name: subTemplate, body: null, context };
4910
4933
  if (ast && ast.type === 2 /* DomNode */) {
4911
4934
  ast.content = [tcall];
4912
4935
  return ast;
@@ -4923,6 +4946,7 @@ function parseTCall(node, ctx) {
4923
4946
  type: 7 /* TCall */,
4924
4947
  name: subTemplate,
4925
4948
  body: body.length ? body : null,
4949
+ context,
4926
4950
  };
4927
4951
  }
4928
4952
  // -----------------------------------------------------------------------------
@@ -5526,8 +5550,7 @@ class App extends TemplateSet {
5526
5550
  return (props, key, ctx, parent, C) => {
5527
5551
  let children = ctx.children;
5528
5552
  let node = children[key];
5529
- if (node &&
5530
- (node.status === 2 /* DESTROYED */ || (isDynamic && node.component.constructor !== C))) {
5553
+ if (isDynamic && node && node.component.constructor !== C) {
5531
5554
  node = undefined;
5532
5555
  }
5533
5556
  const parentFiber = ctx.fiber;
@@ -5736,7 +5759,7 @@ exports.whenReady = whenReady;
5736
5759
  exports.xml = xml;
5737
5760
 
5738
5761
 
5739
- __info__.version = '2.0.0-beta-10';
5740
- __info__.date = '2022-06-22T08:33:26.205Z';
5741
- __info__.hash = '2e03332';
5762
+ __info__.version = '2.0.0-beta-14';
5763
+ __info__.date = '2022-07-08T14:17:53.900Z';
5764
+ __info__.hash = 'd111845';
5742
5765
  __info__.url = 'https://github.com/odoo/owl';
package/dist/owl.es.js CHANGED
@@ -167,6 +167,10 @@ function toClassObj(expr) {
167
167
  for (let key in expr) {
168
168
  const value = expr[key];
169
169
  if (value) {
170
+ key = trim.call(key);
171
+ if (!key) {
172
+ continue;
173
+ }
170
174
  const words = split.call(key, wordRegexp);
171
175
  for (let word of words) {
172
176
  result[word] = value;
@@ -210,7 +214,7 @@ function updateClass(val, oldVal) {
210
214
  function makePropSetter(name) {
211
215
  return function setProp(value) {
212
216
  // support 0, fallback to empty string for other falsy values
213
- this[name] = value === 0 ? 0 : value || "";
217
+ this[name] = value === 0 ? 0 : value ? value.valueOf() : "";
214
218
  };
215
219
  }
216
220
  function isProp(tag, key) {
@@ -1483,6 +1487,7 @@ function cancelFibers(fibers) {
1483
1487
  fiber.render = throwOnRender;
1484
1488
  if (node.status === 0 /* NEW */) {
1485
1489
  node.destroy();
1490
+ delete node.parent.children[node.parentKey];
1486
1491
  }
1487
1492
  node.fiber = null;
1488
1493
  if (fiber.bdom) {
@@ -2871,13 +2876,14 @@ function shallowEqual(l1, l2) {
2871
2876
  return true;
2872
2877
  }
2873
2878
  class LazyValue {
2874
- constructor(fn, ctx, node) {
2879
+ constructor(fn, ctx, component, node) {
2875
2880
  this.fn = fn;
2876
2881
  this.ctx = capture(ctx);
2882
+ this.component = component;
2877
2883
  this.node = node;
2878
2884
  }
2879
2885
  evaluate() {
2880
- return this.fn(this.ctx, this.node);
2886
+ return this.fn.call(this.component, this.ctx, this.node);
2881
2887
  }
2882
2888
  toString() {
2883
2889
  return this.evaluate().toString();
@@ -2886,9 +2892,9 @@ class LazyValue {
2886
2892
  /*
2887
2893
  * Safely outputs `value` as a block depending on the nature of `value`
2888
2894
  */
2889
- function safeOutput(value) {
2890
- if (!value) {
2891
- return value;
2895
+ function safeOutput(value, defaultValue) {
2896
+ if (value === undefined) {
2897
+ return defaultValue ? toggler("default", defaultValue) : toggler("undefined", text(""));
2892
2898
  }
2893
2899
  let safeKey;
2894
2900
  let block;
@@ -3174,7 +3180,7 @@ const STATIC_TOKEN_MAP = Object.assign(Object.create(null), {
3174
3180
  });
3175
3181
  // note that the space after typeof is relevant. It makes sure that the formatted
3176
3182
  // expression has a space after typeof. Currently we don't support delete and void
3177
- const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ".split(",");
3183
+ const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ,|,&,^,~".split(",");
3178
3184
  let tokenizeString = function (expr) {
3179
3185
  let s = expr[0];
3180
3186
  let start = s;
@@ -3668,8 +3674,8 @@ class CodeGenerator {
3668
3674
  define(varName, expr) {
3669
3675
  this.addLine(`const ${varName} = ${expr};`);
3670
3676
  }
3671
- insertAnchor(block) {
3672
- const tag = `block-child-${block.children.length}`;
3677
+ insertAnchor(block, index = block.children.length) {
3678
+ const tag = `block-child-${index}`;
3673
3679
  const anchor = xmlDoc.createElement(tag);
3674
3680
  block.insert(anchor);
3675
3681
  }
@@ -3897,13 +3903,18 @@ class CodeGenerator {
3897
3903
  attrs["block-attribute-" + idx] = attrName;
3898
3904
  }
3899
3905
  else if (key.startsWith("t-att")) {
3906
+ attrName = key === "t-att" ? null : key.slice(6);
3900
3907
  expr = compileExpr(ast.attrs[key]);
3908
+ if (attrName && isProp(ast.tag, attrName)) {
3909
+ // we force a new string or new boolean to bypass the equality check in blockdom when patching same value
3910
+ const C = attrName === "value" ? "String" : "Boolean";
3911
+ expr = `new ${C}(${expr})`;
3912
+ }
3901
3913
  const idx = block.insertData(expr, "attr");
3902
3914
  if (key === "t-att") {
3903
3915
  attrs[`block-attributes`] = String(idx);
3904
3916
  }
3905
3917
  else {
3906
- attrName = key.slice(6);
3907
3918
  attrs[`block-attribute-${idx}`] = attrName;
3908
3919
  }
3909
3920
  }
@@ -4061,20 +4072,37 @@ class CodeGenerator {
4061
4072
  this.insertAnchor(block);
4062
4073
  }
4063
4074
  block = this.createBlock(block, "html", ctx);
4064
- this.helpers.add(ast.expr === "0" ? "zero" : "safeOutput");
4065
- let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`;
4066
- if (ast.body) {
4067
- const nextId = BlockDescription.nextBlockId;
4075
+ let blockStr;
4076
+ if (ast.expr === "0") {
4077
+ this.helpers.add("zero");
4078
+ blockStr = `ctx[zero]`;
4079
+ }
4080
+ else if (ast.body) {
4081
+ let bodyValue = null;
4082
+ bodyValue = BlockDescription.nextBlockId;
4068
4083
  const subCtx = createContext(ctx);
4069
4084
  this.compileAST({ type: 3 /* Multi */, content: ast.body }, subCtx);
4070
- this.helpers.add("withDefault");
4071
- expr = `withDefault(${expr}, b${nextId})`;
4085
+ this.helpers.add("safeOutput");
4086
+ blockStr = `safeOutput(${compileExpr(ast.expr)}, b${bodyValue})`;
4087
+ }
4088
+ else {
4089
+ this.helpers.add("safeOutput");
4090
+ blockStr = `safeOutput(${compileExpr(ast.expr)})`;
4091
+ }
4092
+ this.insertBlock(blockStr, block, ctx);
4093
+ }
4094
+ compileTIfBranch(content, block, ctx) {
4095
+ this.target.indentLevel++;
4096
+ let childN = block.children.length;
4097
+ this.compileAST(content, createContext(ctx, { block, index: ctx.index }));
4098
+ if (block.children.length > childN) {
4099
+ // we have some content => need to insert an anchor at correct index
4100
+ this.insertAnchor(block, childN);
4072
4101
  }
4073
- this.insertBlock(`${expr}`, block, ctx);
4102
+ this.target.indentLevel--;
4074
4103
  }
4075
4104
  compileTIf(ast, ctx, nextNode) {
4076
- let { block, forceNewBlock, index } = ctx;
4077
- let currentIndex = index;
4105
+ let { block, forceNewBlock } = ctx;
4078
4106
  const codeIdx = this.target.code.length;
4079
4107
  const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
4080
4108
  if (block) {
@@ -4084,28 +4112,16 @@ class CodeGenerator {
4084
4112
  block = this.createBlock(block, "multi", ctx);
4085
4113
  }
4086
4114
  this.addLine(`if (${compileExpr(ast.condition)}) {`);
4087
- this.target.indentLevel++;
4088
- this.insertAnchor(block);
4089
- const subCtx = createContext(ctx, { block, index: currentIndex });
4090
- this.compileAST(ast.content, subCtx);
4091
- this.target.indentLevel--;
4115
+ this.compileTIfBranch(ast.content, block, ctx);
4092
4116
  if (ast.tElif) {
4093
4117
  for (let clause of ast.tElif) {
4094
4118
  this.addLine(`} else if (${compileExpr(clause.condition)}) {`);
4095
- this.target.indentLevel++;
4096
- this.insertAnchor(block);
4097
- const subCtx = createContext(ctx, { block, index: currentIndex });
4098
- this.compileAST(clause.content, subCtx);
4099
- this.target.indentLevel--;
4119
+ this.compileTIfBranch(clause.content, block, ctx);
4100
4120
  }
4101
4121
  }
4102
4122
  if (ast.tElse) {
4103
4123
  this.addLine(`} else {`);
4104
- this.target.indentLevel++;
4105
- this.insertAnchor(block);
4106
- const subCtx = createContext(ctx, { block, index: currentIndex });
4107
- this.compileAST(ast.tElse, subCtx);
4108
- this.target.indentLevel--;
4124
+ this.compileTIfBranch(ast.tElse, block, ctx);
4109
4125
  }
4110
4126
  this.addLine("}");
4111
4127
  if (isNewBlock) {
@@ -4263,16 +4279,21 @@ class CodeGenerator {
4263
4279
  }
4264
4280
  compileTCall(ast, ctx) {
4265
4281
  let { block, forceNewBlock } = ctx;
4282
+ let ctxVar = ctx.ctxVar || "ctx";
4283
+ if (ast.context) {
4284
+ ctxVar = generateId("ctx");
4285
+ this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
4286
+ }
4266
4287
  if (ast.body) {
4267
- this.addLine(`ctx = Object.create(ctx);`);
4268
- this.addLine(`ctx[isBoundary] = 1;`);
4288
+ this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
4289
+ this.addLine(`${ctxVar}[isBoundary] = 1;`);
4269
4290
  this.helpers.add("isBoundary");
4270
4291
  const nextId = BlockDescription.nextBlockId;
4271
- const subCtx = createContext(ctx, { preventRoot: true });
4292
+ const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
4272
4293
  this.compileAST({ type: 3 /* Multi */, content: ast.body }, subCtx);
4273
4294
  if (nextId !== BlockDescription.nextBlockId) {
4274
4295
  this.helpers.add("zero");
4275
- this.addLine(`ctx[zero] = b${nextId};`);
4296
+ this.addLine(`${ctxVar}[zero] = b${nextId};`);
4276
4297
  }
4277
4298
  }
4278
4299
  const isDynamic = INTERP_REGEXP.test(ast.name);
@@ -4290,7 +4311,7 @@ class CodeGenerator {
4290
4311
  }
4291
4312
  this.define(templateVar, subTemplate);
4292
4313
  block = this.createBlock(block, "multi", ctx);
4293
- this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block, {
4314
+ this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block, {
4294
4315
  ...ctx,
4295
4316
  forceNewBlock: !block,
4296
4317
  });
@@ -4299,13 +4320,13 @@ class CodeGenerator {
4299
4320
  const id = generateId(`callTemplate_`);
4300
4321
  this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
4301
4322
  block = this.createBlock(block, "multi", ctx);
4302
- this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block, {
4323
+ this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block, {
4303
4324
  ...ctx,
4304
4325
  forceNewBlock: !block,
4305
4326
  });
4306
4327
  }
4307
4328
  if (ast.body && !ctx.isLast) {
4308
- this.addLine(`ctx = ctx.__proto__;`);
4329
+ this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
4309
4330
  }
4310
4331
  }
4311
4332
  compileTCallBlock(ast, ctx) {
@@ -4326,7 +4347,7 @@ class CodeGenerator {
4326
4347
  this.helpers.add("LazyValue");
4327
4348
  const bodyAst = { type: 3 /* Multi */, content: ast.body };
4328
4349
  const name = this.compileInNewTarget("value", bodyAst, ctx);
4329
- let value = `new LazyValue(${name}, ctx, node)`;
4350
+ let value = `new LazyValue(${name}, ctx, this, node)`;
4330
4351
  value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
4331
4352
  this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
4332
4353
  }
@@ -4344,7 +4365,7 @@ class CodeGenerator {
4344
4365
  value = expr;
4345
4366
  }
4346
4367
  this.helpers.add("setContextValue");
4347
- this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`);
4368
+ this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
4348
4369
  }
4349
4370
  }
4350
4371
  generateComponentKey() {
@@ -4466,7 +4487,7 @@ class CodeGenerator {
4466
4487
  id,
4467
4488
  expr: `app.createComponent(${ast.isDynamic ? null : expr}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, ${!ast.props && !ast.dynamicProps})`,
4468
4489
  });
4469
- let blockExpr = `${id}(${propString}, ${keyArg}, node, ctx, ${ast.isDynamic ? expr : null})`;
4490
+ let blockExpr = `${id}(${propString}, ${keyArg}, node, this, ${ast.isDynamic ? expr : null})`;
4470
4491
  if (ast.isDynamic) {
4471
4492
  blockExpr = `toggler(${expr}, ${blockExpr})`;
4472
4493
  }
@@ -4899,10 +4920,12 @@ function parseTCall(node, ctx) {
4899
4920
  return null;
4900
4921
  }
4901
4922
  const subTemplate = node.getAttribute("t-call");
4923
+ const context = node.getAttribute("t-call-context");
4902
4924
  node.removeAttribute("t-call");
4925
+ node.removeAttribute("t-call-context");
4903
4926
  if (node.tagName !== "t") {
4904
4927
  const ast = parseNode(node, ctx);
4905
- const tcall = { type: 7 /* TCall */, name: subTemplate, body: null };
4928
+ const tcall = { type: 7 /* TCall */, name: subTemplate, body: null, context };
4906
4929
  if (ast && ast.type === 2 /* DomNode */) {
4907
4930
  ast.content = [tcall];
4908
4931
  return ast;
@@ -4919,6 +4942,7 @@ function parseTCall(node, ctx) {
4919
4942
  type: 7 /* TCall */,
4920
4943
  name: subTemplate,
4921
4944
  body: body.length ? body : null,
4945
+ context,
4922
4946
  };
4923
4947
  }
4924
4948
  // -----------------------------------------------------------------------------
@@ -5522,8 +5546,7 @@ class App extends TemplateSet {
5522
5546
  return (props, key, ctx, parent, C) => {
5523
5547
  let children = ctx.children;
5524
5548
  let node = children[key];
5525
- if (node &&
5526
- (node.status === 2 /* DESTROYED */ || (isDynamic && node.component.constructor !== C))) {
5549
+ if (isDynamic && node && node.component.constructor !== C) {
5527
5550
  node = undefined;
5528
5551
  }
5529
5552
  const parentFiber = ctx.fiber;
@@ -5700,7 +5723,7 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
5700
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 };
5701
5724
 
5702
5725
 
5703
- __info__.version = '2.0.0-beta-10';
5704
- __info__.date = '2022-06-22T08:33:26.205Z';
5705
- __info__.hash = '2e03332';
5726
+ __info__.version = '2.0.0-beta-14';
5727
+ __info__.date = '2022-07-08T14:17:53.900Z';
5728
+ __info__.hash = 'd111845';
5706
5729
  __info__.url = 'https://github.com/odoo/owl';