DEV: Remove vendored babel and update config for plugins/themes (#17832)
The new plugin list is based on the ones currently used in our ember-cli pipeline, and are based on our official browser support policy. This commit includes an update to the raw-handlebars compiler to remove the 'very hacky but lets us use ES6' code. It's served us well for the last 6 years, but the babel config changes broke it (`const` -> `let`). This commit takes the opportunity to refactor it to take a similar approach to PrettyText, by leaning on `mini-loader.js`.
This commit is contained in:
parent
169f2ad443
commit
7f9c2c0bfb
|
@ -17,6 +17,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.18.5",
|
"@babel/core": "^7.18.5",
|
||||||
|
"@babel/standalone": "^7.18.12",
|
||||||
"@discourse/itsatrap": "^2.0.10",
|
"@discourse/itsatrap": "^2.0.10",
|
||||||
"@ember/jquery": "^2.0.0",
|
"@ember/jquery": "^2.0.0",
|
||||||
"@ember/optional-features": "^2.0.0",
|
"@ember/optional-features": "^2.0.0",
|
||||||
|
|
|
@ -957,6 +957,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/standalone@^7.18.12":
|
||||||
|
version "7.18.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.18.12.tgz#4c0abdf1b5213394e73a0ba5500dcc287194a20d"
|
||||||
|
integrity sha512-wDh3K5IUJiSMAY0MLYBFoCaj2RCZwvDz5BHn2uHat9KOsGWEVDFgFQFIOO+81Js2phFKNppLC45iOCsZVfJniw==
|
||||||
|
|
||||||
"@babel/template@^7.16.7", "@babel/template@^7.18.6":
|
"@babel/template@^7.16.7", "@babel/template@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31"
|
||||||
|
|
|
@ -4,6 +4,25 @@ require 'mini_racer'
|
||||||
|
|
||||||
class DiscourseJsProcessor
|
class DiscourseJsProcessor
|
||||||
|
|
||||||
|
DISCOURSE_COMMON_BABEL_PLUGINS = [
|
||||||
|
'proposal-optional-chaining',
|
||||||
|
['proposal-decorators', { legacy: true } ],
|
||||||
|
'transform-template-literals',
|
||||||
|
'proposal-class-properties',
|
||||||
|
'proposal-class-static-block',
|
||||||
|
'proposal-private-property-in-object',
|
||||||
|
'proposal-private-methods',
|
||||||
|
'proposal-numeric-separator',
|
||||||
|
'proposal-logical-assignment-operators',
|
||||||
|
'proposal-nullish-coalescing-operator',
|
||||||
|
'proposal-json-strings',
|
||||||
|
'proposal-optional-catch-binding',
|
||||||
|
'transform-parameters',
|
||||||
|
'proposal-async-generator-functions',
|
||||||
|
'proposal-object-rest-spread',
|
||||||
|
'proposal-export-namespace-from',
|
||||||
|
]
|
||||||
|
|
||||||
def self.plugin_transpile_paths
|
def self.plugin_transpile_paths
|
||||||
@@plugin_transpile_paths ||= Set.new
|
@@plugin_transpile_paths ||= Set.new
|
||||||
end
|
end
|
||||||
|
@ -94,9 +113,10 @@ class DiscourseJsProcessor
|
||||||
def self.create_new_context
|
def self.create_new_context
|
||||||
# timeout any eval that takes longer than 15 seconds
|
# timeout any eval that takes longer than 15 seconds
|
||||||
ctx = MiniRacer::Context.new(timeout: 15000, ensure_gc_after_idle: 2000)
|
ctx = MiniRacer::Context.new(timeout: 15000, ensure_gc_after_idle: 2000)
|
||||||
ctx.eval("var self = this; #{File.read("#{Rails.root}/vendor/assets/javascripts/babel.js")}")
|
ctx.eval("#{File.read("#{Rails.root}/app/assets/javascripts/node_modules/@babel/standalone/babel.js")}")
|
||||||
ctx.eval(File.read(Ember::Source.bundled_path_for('ember-template-compiler.js')))
|
ctx.eval(File.read(Ember::Source.bundled_path_for('ember-template-compiler.js')))
|
||||||
ctx.eval("module = {}; exports = {};")
|
ctx.eval("module = {}; exports = {};")
|
||||||
|
ctx.eval("const DISCOURSE_COMMON_BABEL_PLUGINS = #{DISCOURSE_COMMON_BABEL_PLUGINS.to_json};")
|
||||||
ctx.attach("rails.logger.info", proc { |err| Rails.logger.info(err.to_s) })
|
ctx.attach("rails.logger.info", proc { |err| Rails.logger.info(err.to_s) })
|
||||||
ctx.attach("rails.logger.error", proc { |err| Rails.logger.error(err.to_s) })
|
ctx.attach("rails.logger.error", proc { |err| Rails.logger.error(err.to_s) })
|
||||||
ctx.eval <<JS
|
ctx.eval <<JS
|
||||||
|
@ -156,9 +176,34 @@ JS
|
||||||
|
|
||||||
if opts[:module_name] && !@skip_module
|
if opts[:module_name] && !@skip_module
|
||||||
filename = opts[:filename] || 'unknown'
|
filename = opts[:filename] || 'unknown'
|
||||||
"Babel.transform(#{js_source}, { moduleId: '#{opts[:module_name]}', filename: '#{filename}', ast: false, presets: ['es2015'], plugins: [['transform-modules-amd', {noInterop: true}], 'proposal-object-rest-spread', 'proposal-optional-chaining', ['proposal-decorators', {legacy: true} ], 'proposal-class-properties', exports.WidgetHbsCompiler] }).code"
|
<<~JS
|
||||||
|
Babel.transform(
|
||||||
|
#{js_source},
|
||||||
|
{
|
||||||
|
moduleId: '#{opts[:module_name]}',
|
||||||
|
filename: '#{filename}',
|
||||||
|
ast: false,
|
||||||
|
plugins: [
|
||||||
|
exports.WidgetHbsCompiler,
|
||||||
|
['transform-modules-amd', {noInterop: true}],
|
||||||
|
...DISCOURSE_COMMON_BABEL_PLUGINS
|
||||||
|
]
|
||||||
|
}
|
||||||
|
).code
|
||||||
|
JS
|
||||||
else
|
else
|
||||||
"Babel.transform(#{js_source}, { ast: false, plugins: ['proposal-json-strings', 'proposal-nullish-coalescing-operator', 'proposal-logical-assignment-operators', 'proposal-numeric-separator', 'proposal-optional-catch-binding', 'transform-dotall-regex', 'proposal-unicode-property-regex', 'transform-named-capturing-groups-regex', 'proposal-object-rest-spread', 'proposal-optional-chaining', 'transform-arrow-functions', 'transform-block-scoped-functions', 'transform-block-scoping', 'transform-computed-properties', 'transform-destructuring', 'transform-duplicate-keys', 'transform-for-of', 'transform-function-name', 'transform-literals', 'transform-object-super', 'transform-parameters', 'transform-shorthand-properties', 'transform-spread', 'transform-sticky-regex', 'transform-template-literals', 'transform-typeof-symbol', 'transform-unicode-regex', ['proposal-decorators', {legacy: true}], 'proposal-class-properties', exports.WidgetHbsCompiler] }).code"
|
<<~JS
|
||||||
|
Babel.transform(
|
||||||
|
#{js_source},
|
||||||
|
{
|
||||||
|
ast: false,
|
||||||
|
plugins: [
|
||||||
|
exports.WidgetHbsCompiler,
|
||||||
|
...DISCOURSE_COMMON_BABEL_PLUGINS
|
||||||
|
]
|
||||||
|
}
|
||||||
|
).code
|
||||||
|
JS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,20 +10,20 @@ class Barber::Precompiler
|
||||||
|
|
||||||
def precompiler
|
def precompiler
|
||||||
if !@precompiler
|
if !@precompiler
|
||||||
|
loader = File.read("#{Rails.root}/app/assets/javascripts/mini-loader.js")
|
||||||
source = File.read("#{Rails.root}/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js")
|
source = File.read("#{Rails.root}/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js")
|
||||||
transpiler = DiscourseJsProcessor::Transpiler.new(skip_module: true)
|
|
||||||
transpiled = transpiler.perform(source)
|
|
||||||
|
|
||||||
# very hacky but lets us use ES6. I'm ashamed of this code -RW
|
transpiled = DiscourseJsProcessor.transpile(source, "#{Rails.root}/app/assets/javascripts/", "discourse-common/lib/raw-handlebars")
|
||||||
transpiled = transpiled[transpiled.index('var RawHandlebars = ')...transpiled.index('export ')]
|
|
||||||
|
|
||||||
@precompiler = StringIO.new <<~JS
|
@precompiler = StringIO.new <<~JS
|
||||||
var __RawHandlebars;
|
let __RawHandlebars;
|
||||||
(function() {
|
|
||||||
#{transpiled};
|
(function(){
|
||||||
__RawHandlebars = RawHandlebars;
|
#{loader}
|
||||||
})();
|
define("handlebars", ["exports"], function(exports){ exports.default = Handlebars; })
|
||||||
|
#{transpiled}
|
||||||
|
__RawHandlebars = require("discourse-common/lib/raw-handlebars").default;
|
||||||
|
})()
|
||||||
|
|
||||||
Barber = {
|
Barber = {
|
||||||
precompile: function(string) {
|
precompile: function(string) {
|
||||||
|
@ -31,6 +31,7 @@ class Barber::Precompiler
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
JS
|
JS
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@precompiler
|
@precompiler
|
||||||
|
|
|
@ -197,7 +197,7 @@ HTML
|
||||||
expect(theme.javascript_cache.content).to include('addRawTemplate("discovery"')
|
expect(theme.javascript_cache.content).to include('addRawTemplate("discovery"')
|
||||||
expect(theme.javascript_cache.content).to include("define(\"discourse/theme-#{theme.id}/controllers/discovery\"")
|
expect(theme.javascript_cache.content).to include("define(\"discourse/theme-#{theme.id}/controllers/discovery\"")
|
||||||
expect(theme.javascript_cache.content).to include("define(\"discourse/theme-#{theme.id}/controllers/discovery-2\"")
|
expect(theme.javascript_cache.content).to include("define(\"discourse/theme-#{theme.id}/controllers/discovery-2\"")
|
||||||
expect(theme.javascript_cache.content).to include("var settings =")
|
expect(theme.javascript_cache.content).to include("const settings =")
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_upload_theme_field!(name)
|
def create_upload_theme_field!(name)
|
||||||
|
|
|
@ -248,22 +248,8 @@ HTML
|
||||||
)
|
)
|
||||||
expect(javascript_cache.content).to include("name: \"theme-field-#{field.id}-mobile-html-script-1\",")
|
expect(javascript_cache.content).to include("name: \"theme-field-#{field.id}-mobile-html-script-1\",")
|
||||||
expect(javascript_cache.content).to include("after: \"inject-objects\",")
|
expect(javascript_cache.content).to include("after: \"inject-objects\",")
|
||||||
expect(javascript_cache.content).to include("(0, _pluginApi.withPluginApi)(\"0.1\", function (api) {")
|
expect(javascript_cache.content).to include("(0, _pluginApi.withPluginApi)(\"0.1\", api =>")
|
||||||
expect(javascript_cache.content).to include("var x = 1;")
|
expect(javascript_cache.content).to include("const x = 1;")
|
||||||
end
|
|
||||||
|
|
||||||
it "replaces const writes with _readOnlyError function call" do
|
|
||||||
html = <<HTML
|
|
||||||
<script type='text/discourse-plugin' version='0.1'>
|
|
||||||
const x = 1;
|
|
||||||
x = 2;
|
|
||||||
</script>
|
|
||||||
HTML
|
|
||||||
|
|
||||||
baked, javascript_cache = transpile(html)
|
|
||||||
expect(baked).to include(javascript_cache.url)
|
|
||||||
expect(javascript_cache.content).to include('var x = 1;')
|
|
||||||
expect(javascript_cache.content).to include('2, _readOnlyError("x");')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -369,9 +355,9 @@ HTML
|
||||||
)
|
)
|
||||||
expect(theme_field.javascript_cache.content).to include("name: \"theme-field-#{theme_field.id}-common-html-script-1\",")
|
expect(theme_field.javascript_cache.content).to include("name: \"theme-field-#{theme_field.id}-common-html-script-1\",")
|
||||||
expect(theme_field.javascript_cache.content).to include("after: \"inject-objects\",")
|
expect(theme_field.javascript_cache.content).to include("after: \"inject-objects\",")
|
||||||
expect(theme_field.javascript_cache.content).to include("(0, _pluginApi.withPluginApi)(\"1.0\", function (api)")
|
expect(theme_field.javascript_cache.content).to include("(0, _pluginApi.withPluginApi)(\"1.0\", api =>")
|
||||||
expect(theme_field.javascript_cache.content).to include("alert(settings.name)")
|
expect(theme_field.javascript_cache.content).to include("alert(settings.name)")
|
||||||
expect(theme_field.javascript_cache.content).to include("var a = function a() {}")
|
expect(theme_field.javascript_cache.content).to include("let a = () => {}")
|
||||||
|
|
||||||
setting = theme.settings.find { |s| s.name == :name }
|
setting = theme.settings.find { |s| s.name == :name }
|
||||||
setting.value = 'bill'
|
setting.value = 'bill'
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue