From 2b2434b82d2c7919e764248f756246d5f1d686b2 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 29 May 2020 14:37:02 -0400 Subject: [PATCH] Start Discourse in an initializer (#9930) * DEV: To be pedantic, there is more than EMBER in there now * DEV: Use less globals. Have `Discourse` start in an initializer * DEV: Remove another global --- app/assets/javascripts/discourse-loader.js | 10 +- .../pre-initializers/discourse-bootstrap.js | 94 +++++++++++++++++++ .../inject-discourse-objects.js | 1 + .../discourse/app/widgets/post-stream.js | 3 +- .../javascripts/preload-application-data.js | 84 ----------------- app/assets/javascripts/start-discourse.js | 4 + app/views/layouts/application.html.erb | 2 +- config/application.rb | 2 +- lib/discourse_js_processor.rb | 2 +- test/javascripts/test_helper.js | 2 - 10 files changed, 109 insertions(+), 95 deletions(-) create mode 100644 app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js delete mode 100644 app/assets/javascripts/preload-application-data.js create mode 100644 app/assets/javascripts/start-discourse.js diff --git a/app/assets/javascripts/discourse-loader.js b/app/assets/javascripts/discourse-loader.js index fc829ae12f0..f6a28c01cb4 100644 --- a/app/assets/javascripts/discourse-loader.js +++ b/app/assets/javascripts/discourse-loader.js @@ -1,7 +1,7 @@ var define, requirejs; (function() { - var EMBER_MODULES = {}; + var JS_MODULES = {}; var ALIASES = { "ember-addons/ember-computed-decorators": "discourse-common/utils/decorators", @@ -11,7 +11,7 @@ var define, requirejs; // In future versions of ember we don't need this if (typeof Ember !== "undefined") { - EMBER_MODULES = { + JS_MODULES = { jquery: { default: $ }, "@ember/array": { default: Ember.Array, @@ -285,7 +285,7 @@ var define, requirejs; name = "@ember/object"; } - var mod = EMBER_MODULES[name] || registry[name]; + var mod = JS_MODULES[name] || registry[name]; if (!mod) { throw new Error( "Could not find module `" + name + "` imported from `" + origin + "`" @@ -308,8 +308,8 @@ var define, requirejs; requirejs = require = function(name) { name = transformForAliases(name); - if (EMBER_MODULES[name]) { - return EMBER_MODULES[name]; + if (JS_MODULES[name]) { + return JS_MODULES[name]; } var mod = registry[name]; diff --git a/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js b/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js new file mode 100644 index 00000000000..494ed5e2e91 --- /dev/null +++ b/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js @@ -0,0 +1,94 @@ +import PreloadStore from "discourse/lib/preload-store"; +import I18n from "I18n"; +import Session from "discourse/models/session"; +import RSVP from "rsvp"; +import { isTesting } from "discourse-common/config/environment"; + +export default { + name: "discourse-bootstrap", + + // The very first initializer to run + initialize(container, app) { + // Our test environment has its own bootstrap code + if (isTesting()) { + return; + } + const preloadedDataElement = document.getElementById("data-preloaded"); + const setupData = document.getElementById("data-discourse-setup").dataset; + + if (preloadedDataElement) { + const preloaded = JSON.parse(preloadedDataElement.dataset.preloaded); + + Object.keys(preloaded).forEach(function(key) { + PreloadStore.store(key, JSON.parse(preloaded[key])); + + if (setupData.debugPreloadedAppData === "true") { + /* eslint-disable no-console */ + console.log(key, PreloadStore.get(key)); + /* eslint-enable no-console */ + } + }); + } + + app.CDN = setupData.cdn; + app.BaseUrl = setupData.baseUrl; + app.BaseUri = setupData.baseUri; + app.Environment = setupData.environment; + app.SiteSettings = PreloadStore.get("siteSettings"); + app.ThemeSettings = PreloadStore.get("themeSettings"); + app.LetterAvatarVersion = setupData.letterAvatarVersion; + app.MarkdownItURL = setupData.markdownItUrl; + app.ServiceWorkerURL = setupData.serviceWorkerUrl; + I18n.defaultLocale = setupData.defaultLocale; + + window.Logster = window.Logster || {}; + window.Logster.enabled = setupData.enableJsErrorReporting === "true"; + + app.set("assetVersion", setupData.assetVersion); + + Session.currentProp( + "disableCustomCSS", + setupData.disableCustomCss === "true" + ); + + if (setupData.safeMode) { + Session.currentProp("safe_mode", setupData.safeMode); + } + + app.HighlightJSPath = setupData.highlightJsPath; + app.SvgSpritePath = setupData.svgSpritePath; + + if (app.Environment === "development") { + app.SvgIconList = setupData.svgIconList; + } + + if (setupData.s3BaseUrl) { + app.S3CDN = setupData.s3Cdn; + app.S3BaseUrl = setupData.s3BaseUrl; + } + + RSVP.configure("onerror", function(e) { + // Ignore TransitionAborted exceptions that bubble up + if (e && e.message === "TransitionAborted") { + return; + } + + if (Discourse.Environment === "development") { + /* eslint-disable no-console */ + if (e) { + if (e.message || e.stack) { + console.log(e.message); + console.log(e.stack); + } else { + console.log("Uncaught promise: ", e); + } + } else { + console.log("A promise failed but was not caught."); + } + /* eslint-enable no-console */ + } + + window.onerror(e && e.message, null, null, null, e); + }); + } +}; diff --git a/app/assets/javascripts/discourse/app/pre-initializers/inject-discourse-objects.js b/app/assets/javascripts/discourse/app/pre-initializers/inject-discourse-objects.js index 045798e6a06..9c2a3e47799 100644 --- a/app/assets/javascripts/discourse/app/pre-initializers/inject-discourse-objects.js +++ b/app/assets/javascripts/discourse/app/pre-initializers/inject-discourse-objects.js @@ -15,6 +15,7 @@ const ALL_TARGETS = ["controller", "component", "route", "model", "adapter"]; export default { name: "inject-discourse-objects", + after: "discourse-bootstrap", initialize(container, app) { ALL_TARGETS.forEach(t => app.inject(t, "appEvents", "service:app-events")); diff --git a/app/assets/javascripts/discourse/app/widgets/post-stream.js b/app/assets/javascripts/discourse/app/widgets/post-stream.js index 6406d1c9e81..1ccb12f4628 100644 --- a/app/assets/javascripts/discourse/app/widgets/post-stream.js +++ b/app/assets/javascripts/discourse/app/widgets/post-stream.js @@ -3,6 +3,7 @@ import { createWidget } from "discourse/widgets/widget"; import transformPost from "discourse/lib/transform-post"; import { Placeholder } from "discourse/lib/posts-with-placeholders"; import { addWidgetCleanCallback } from "discourse/components/mount-widget"; +import { isTesting } from "discourse-common/config/environment"; let transformCallbacks = null; export function postTransformCallbacks(transformed) { @@ -19,7 +20,7 @@ export function addPostTransformCallback(callback) { transformCallbacks.push(callback); } -const CLOAKING_ENABLED = !window.inTestEnv; +const CLOAKING_ENABLED = !isTesting(); const DAY = 1000 * 60 * 60 * 24; const _dontCloak = {}; diff --git a/app/assets/javascripts/preload-application-data.js b/app/assets/javascripts/preload-application-data.js deleted file mode 100644 index bb11ecbea43..00000000000 --- a/app/assets/javascripts/preload-application-data.js +++ /dev/null @@ -1,84 +0,0 @@ -// discourse-skip-module -(function() { - const ps = require("discourse/lib/preload-store").default; - const preloadedDataElement = document.getElementById("data-preloaded"); - const setupData = document.getElementById("data-discourse-setup").dataset; - const I18n = require("I18n").default; - - if (preloadedDataElement) { - const preloaded = JSON.parse(preloadedDataElement.dataset.preloaded); - - Object.keys(preloaded).forEach(function(key) { - ps.store(key, JSON.parse(preloaded[key])); - - if (setupData.debugPreloadedAppData === "true") { - /* eslint-disable no-console */ - console.log(key, ps.get(key)); - /* eslint-enable no-console */ - } - }); - } - - window.Logster = window.Logster || {}; - window.Logster.enabled = setupData.enableJsErrorReporting === "true"; - - Discourse.CDN = setupData.cdn; - Discourse.BaseUrl = setupData.baseUrl; - Discourse.BaseUri = setupData.baseUri; - Discourse.Environment = setupData.environment; - Discourse.SiteSettings = ps.get("siteSettings"); - Discourse.ThemeSettings = ps.get("themeSettings"); - Discourse.LetterAvatarVersion = setupData.letterAvatarVersion; - Discourse.MarkdownItURL = setupData.markdownItUrl; - Discourse.ServiceWorkerURL = setupData.serviceWorkerUrl; - I18n.defaultLocale = setupData.defaultLocale; - Discourse.start(); - Discourse.set("assetVersion", setupData.assetVersion); - - const Session = require("discourse/models/session").default; - Session.currentProp( - "disableCustomCSS", - setupData.disableCustomCss === "true" - ); - - if (setupData.safeMode) { - Session.currentProp("safe_mode", setupData.safeMode); - } - - Discourse.HighlightJSPath = setupData.highlightJsPath; - Discourse.SvgSpritePath = setupData.svgSpritePath; - - if (Discourse.Environment === "development") { - Discourse.SvgIconList = setupData.svgIconList; - } - - if (setupData.s3BaseUrl) { - Discourse.S3CDN = setupData.s3Cdn; - Discourse.S3BaseUrl = setupData.s3BaseUrl; - } - - // eslint-disable-next-line - Ember.RSVP.configure("onerror", function(e) { - // Ignore TransitionAborted exceptions that bubble up - if (e && e.message === "TransitionAborted") { - return; - } - - if (Discourse.Environment === "development") { - /* eslint-disable no-console */ - if (e) { - if (e.message || e.stack) { - console.log(e.message); - console.log(e.stack); - } else { - console.log("Uncaught promise: ", e); - } - } else { - console.log("A promise failed but was not caught."); - } - /* eslint-enable no-console */ - } - - window.onerror(e && e.message, null, null, null, e); - }); -})(); diff --git a/app/assets/javascripts/start-discourse.js b/app/assets/javascripts/start-discourse.js new file mode 100644 index 00000000000..cabffc4a5ec --- /dev/null +++ b/app/assets/javascripts/start-discourse.js @@ -0,0 +1,4 @@ +// discourse-skip-module +(function() { + Discourse.start(); +})(); diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 862e00f2db6..9cb5efcce97 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -109,7 +109,7 @@ <% end %> - <%= preload_script "preload-application-data" %> + <%= preload_script "start-discourse" %> <%= yield :data %> diff --git a/config/application.rb b/config/application.rb index 3f0f558f03a..f2cbb143912 100644 --- a/config/application.rb +++ b/config/application.rb @@ -154,7 +154,7 @@ module Discourse service-worker.js google-tag-manager.js google-universal-analytics.js - preload-application-data.js + start-discourse.js print-page.js omniauth-complete.js activate-account.js diff --git a/lib/discourse_js_processor.rb b/lib/discourse_js_processor.rb index df5e35c6972..274fda206d9 100644 --- a/lib/discourse_js_processor.rb +++ b/lib/discourse_js_processor.rb @@ -48,7 +48,7 @@ class DiscourseJsProcessor return false if relative_path.start_with?("#{js_root}/plugins/") return true if %w( - preload-application-data + start-discourse wizard-start onpopstate-handler google-tag-manager diff --git a/test/javascripts/test_helper.js b/test/javascripts/test_helper.js index 5e7c155edd0..cc599032a10 100644 --- a/test/javascripts/test_helper.js +++ b/test/javascripts/test_helper.js @@ -53,8 +53,6 @@ sinon.config = { useFakeServer: false }; -window.inTestEnv = true; - let MessageBus = require("message-bus-client").default; // Stop the message bus so we don't get ajax calls