diff --git a/src/component/component.ts b/src/component/component.ts index f2297b11..b8a4039a 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -1,7 +1,6 @@ import { Observer } from "../core/observer"; import { CompiledTemplate, QWeb } from "../qweb/index"; import { h, patch, VNode } from "../vdom/index"; -import { config } from "../config"; import "./directive"; import { Fiber } from "./fiber"; import "./props_validation"; @@ -88,6 +87,7 @@ export class Component { static components = {}; static props?: any; static defaultProps?: any; + static env: any = {}; /** * The `el` is the root element of the component. Note that it could be null: @@ -131,7 +131,10 @@ export class Component { depth = __powl__.depth + 1; } else { // we are the root component - this.env = config.env as T; + this.env = (this.constructor as any).env; + if (!this.env.qweb) { + this.env.qweb = new QWeb(); + } this.props = undefined as unknown as Props; this.env.qweb.on("update", this, () => { if (this.__owl__.isMounted) { diff --git a/src/config.ts b/src/config.ts index 9056a923..5deac5c4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,4 @@ import { QWeb } from "./qweb/index"; -import { Env } from "./component/component"; /** * This file creates and exports the OWL 'config' object, with keys: @@ -8,7 +7,6 @@ import { Env } from "./component/component"; */ interface Config { - env: Env; mode: string; } @@ -30,19 +28,3 @@ Object.defineProperty(config, "mode", { } }, }); - -let env:Env; -Object.defineProperty(config, "env", { - get() { - if (!env) { - env = {} as Env; - } - if (!env.qweb) { - env.qweb = new QWeb(); - } - return env; - }, - set(newEnv: Env) { - env = newEnv; - }, -}); diff --git a/tests/animations.test.ts b/tests/animations.test.ts index 2326f8aa..3e148c39 100644 --- a/tests/animations.test.ts +++ b/tests/animations.test.ts @@ -1,5 +1,4 @@ import { Component, Env } from "../src/component/component"; -import { config } from "../src/config"; import { QWeb } from "../src/qweb/index"; import { useState, useRef } from "../src/hooks"; import { @@ -30,7 +29,7 @@ let cssEl: HTMLElement; beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; qweb = new QWeb(); }); diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index fecd99c3..a6270dca 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -3,7 +3,6 @@ import { QWeb } from "../../src/qweb/qweb"; import { xml } from "../../src/tags"; import { useState, useRef } from "../../src/hooks"; import { EventBus } from "../../src/core/event_bus"; -import { config } from "../../src/config"; import { makeDeferred, makeTestFixture, @@ -36,7 +35,7 @@ beforeEach(() => { ); env.qweb.addTemplate("WidgetA", `
Hello
`); env.qweb.addTemplate("WidgetB", `
world
`); - config.env = env; + Component.env = env; }); afterEach(() => { @@ -3457,7 +3456,7 @@ describe("can deduce template from name", () => { await abc.mount(fixture); expect(fixture.innerHTML).toBe("Rochefort 8"); abc.destroy(); - config.env = env2; + Component.env = env2; const abc2 = new ABC(); await abc2.mount(fixture); expect(fixture.innerHTML).toBe("Rochefort 10"); @@ -4247,6 +4246,31 @@ describe("environment and plugins", () => { await nextTick(); expect(fixture.innerHTML).toBe("
Blue
"); }); + + test("can define specific env for root components", async () => { + class App1 extends Component { + static template = xml``; + } + App1.env = { test: 1 }; + class App2 extends Component { + static template = xml``; + } + App2.env = { test: 2 }; + class App1B extends App1 {} + class App2B extends App2 {} + App2B.env = { test: 3 }; + + const app1 = new App1(); + const app2 = new App2(); + const app1B = new App1B(); + const app2B = new App2B(); + + expect(app1.env.qweb).toBeDefined(); + expect(app1.env.test).toBe(1); + expect(app2.env.test).toBe(2); + expect(app1B.env.test).toBe(1); + expect(app2B.env.test).toBe(3); + }); }); describe("component error handling (catchError)", () => { diff --git a/tests/component/props_validation.test.ts b/tests/component/props_validation.test.ts index f42add69..8da25451 100644 --- a/tests/component/props_validation.test.ts +++ b/tests/component/props_validation.test.ts @@ -1,7 +1,6 @@ import { Component, Env } from "../../src/component/component"; import { makeTestFixture, makeTestEnv, nextTick } from "../helpers"; import { useState } from "../../src/hooks"; -import { config } from "../../src/config"; import { QWeb } from "../../src/qweb"; import { xml } from "../../src/tags"; @@ -16,7 +15,7 @@ let dev: boolean = false; beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; dev = QWeb.dev; QWeb.dev = true; }); diff --git a/tests/context.test.ts b/tests/context.test.ts index 6e0e3460..64e64487 100644 --- a/tests/context.test.ts +++ b/tests/context.test.ts @@ -1,7 +1,6 @@ import { makeDeferred, makeTestEnv, makeTestFixture, nextTick } from "./helpers"; import { Component } from "../src/component/component"; import { Context, useContext } from "../src/context"; -import { config } from "../src/config"; import { xml } from "../src/tags"; import { useState } from "../src/hooks"; @@ -18,7 +17,7 @@ let fixture: HTMLElement; beforeEach(() => { fixture = makeTestFixture(); - config.env = makeTestEnv(); + Component.env = makeTestEnv(); }); afterEach(() => { diff --git a/tests/hooks.test.ts b/tests/hooks.test.ts index 810bdfc5..e8b9edc8 100644 --- a/tests/hooks.test.ts +++ b/tests/hooks.test.ts @@ -1,6 +1,5 @@ import { makeTestEnv, makeTestFixture, nextTick } from "./helpers"; import { Component, Env } from "../src/component/component"; -import { config } from "../src/config"; import { useState, onMounted, @@ -29,7 +28,7 @@ let env: Env; beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; }); afterEach(() => { diff --git a/tests/misc/async_root.test.ts b/tests/misc/async_root.test.ts index 66a6c9ee..39adad77 100644 --- a/tests/misc/async_root.test.ts +++ b/tests/misc/async_root.test.ts @@ -1,5 +1,4 @@ import { AsyncRoot } from "../../src/misc/async_root"; -import { config } from "../../src/config"; import { useState } from "../../src/hooks"; import { xml } from "../../src/tags"; import { makeDeferred, makeTestFixture, makeTestEnv, nextTick } from "../helpers"; @@ -18,7 +17,7 @@ let fixture: HTMLElement; beforeEach(() => { fixture = makeTestFixture(); - config.env = makeTestEnv(); + Component.env = makeTestEnv(); }); afterEach(() => { diff --git a/tests/router/link.test.ts b/tests/router/link.test.ts index 58a3761b..74bf7c73 100644 --- a/tests/router/link.test.ts +++ b/tests/router/link.test.ts @@ -1,5 +1,4 @@ import { Component } from "../../src/component/component"; -import { config } from "../../src/config"; import { Link } from "../../src/router/link"; import { RouterEnv } from "../../src/router/router"; import { makeTestEnv, makeTestFixture, nextTick } from "../helpers"; @@ -13,7 +12,7 @@ describe("Link component", () => { beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; }); afterEach(() => { diff --git a/tests/router/route_component.test.ts b/tests/router/route_component.test.ts index 0ec00183..831e7149 100644 --- a/tests/router/route_component.test.ts +++ b/tests/router/route_component.test.ts @@ -1,5 +1,4 @@ import { Component } from "../../src/component/component"; -import { config } from "../../src/config"; import { RouterEnv } from "../../src/router/router"; import { RouteComponent } from "../../src/router/route_component"; import { makeTestEnv, makeTestFixture, nextTick } from "../helpers"; @@ -13,7 +12,7 @@ describe("RouteComponent", () => { beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; }); afterEach(() => { diff --git a/tests/store_hooks.test.ts b/tests/store_hooks.test.ts index e904f004..729dcc08 100644 --- a/tests/store_hooks.test.ts +++ b/tests/store_hooks.test.ts @@ -1,5 +1,4 @@ import { Component, Env } from "../src/component/component"; -import { config } from "../src/config"; import { Store, useStore, useDispatch, useGetters } from "../src/store"; import { useState } from "../src/hooks"; import { xml } from "../src/tags"; @@ -13,7 +12,7 @@ describe("connecting a component to store", () => { beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; }); afterEach(() => { @@ -922,7 +921,7 @@ describe("various scenarios", () => { beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - config.env = env; + Component.env = env; }); afterEach(() => { diff --git a/tools/benchmarks/owl-master/app.js b/tools/benchmarks/owl-master/app.js index 45515750..caa88b4b 100644 --- a/tools/benchmarks/owl-master/app.js +++ b/tools/benchmarks/owl-master/app.js @@ -144,7 +144,7 @@ App.components = { Message }; //------------------------------------------------------------------------------ async function start() { const templates = await owl.utils.loadFile("templates.xml"); - owl.config.env = { + App.env = { qweb: new owl.QWeb({ templates }) }; const app = new App(); diff --git a/tools/playground/app.js b/tools/playground/app.js index 70267071..d07ca6ec 100644 --- a/tools/playground/app.js +++ b/tools/playground/app.js @@ -95,7 +95,7 @@ function makeCodeIframe(js, css, xml, errorHandler) { owl.__info__.mode = 'dev'; let templates = \`${sanitizedXML}\`; const qweb = new owl.QWeb({ templates }); - owl.config.env = { qweb }; + owl.Component.env = { qweb }; } ${js}`; script.innerHTML = content; @@ -443,7 +443,7 @@ async function start() { owl.utils.whenReady() ]); const qweb = new owl.QWeb({ templates }); - owl.config.env = { qweb }; + owl.Component.env = { qweb }; const app = new App(); app.mount(document.body); } diff --git a/tools/playground/samples.js b/tools/playground/samples.js index b47f8e35..ab1384f6 100644 --- a/tools/playground/samples.js +++ b/tools/playground/samples.js @@ -345,7 +345,7 @@ const themeContext = new Context({ foreground: '#fff', }); // Add the themeContext the environment to make it available to all components -owl.config.env.themeContext = themeContext; +App.env.themeContext = themeContext; const app = new App(); app.mount(document.body); `; @@ -544,7 +544,7 @@ function makeStore() { return store; } -owl.config.env.store = makeStore(); +TodoApp.env.store = makeStore(); const app = new TodoApp(); app.mount(document.body); `; @@ -1032,7 +1032,7 @@ function setupResponsivePlugin(env) { //------------------------------------------------------------------------------ // Application Startup //------------------------------------------------------------------------------ -setupResponsivePlugin(owl.config.env); +setupResponsivePlugin(App.env); const app = new App(); app.mount(document.body); @@ -1543,7 +1543,7 @@ const windows = [ } ]; -owl.config.env.windows = windows; +App.env.windows = windows; const app = new App(); app.mount(document.body); `;