# frozen_string_literal: true
require 'set'
module Opal
module Config
extend self
private
def config_options
@config_options ||= {}
end
# Defines a new configuration option
#
# @param [String] name the option name
# @param [Object] default_value the option's default value
# @!macro [attach] property
# @!attribute [rw] $1
def config_option(name, default_value, options = {})
compiler = options.fetch(:compiler_option, nil)
valid_values = options.fetch(:valid_values, [true, false])
config_options[name] = {
default: default_value,
compiler: compiler
}
define_singleton_method(name) { config.fetch(name, default_value) }
define_singleton_method("#{name}=") do |value|
unless valid_values.any? { |valid_value| valid_value === value }
raise ArgumentError, "Not a valid value for option #{self}.#{name}, provided #{value.inspect}. "\
"Must be #{valid_values.inspect} === #{value.inspect}"
end
config[name] = value
end
end
public
# @return [Hash] the default configuration
def default_config
default_config = {}
config_options.each do |name, options|
default_value = options.fetch(:default)
default_value = Proc === default_value ? default_value.call : default_value
default_config[name] = default_value
end
default_config
end
# @return [Hash] the configuration for Opal::Compiler
def compiler_options
compiler_options = {}
config_options.each do |name, options|
compiler_option_name = options.fetch(:compiler)
compiler_options[compiler_option_name] = config.fetch(name)
end
compiler_options
end
# @return [Hash] the current configuration, defaults to #default_config
def config
@config ||= default_config
end
# Resets the config to its default value
#
# @return [void]
def reset!
@config = nil
end
# Enable method_missing support.
#
# @return [true, false]
config_option :method_missing_enabled, true, compiler_option: :method_missing
# Enable const_missing support.
#
# @return [true, false]
config_option :const_missing_enabled, true, compiler_option: :const_missing
# Enable arity check on the arguments passed to methods, procs and lambdas.
#
# @return [true, false]
config_option :arity_check_enabled, false, compiler_option: :arity_check
# Add stubs for methods related to freezing objects (for compatibility).
#
# @return [true, false]
config_option :freezing_stubs_enabled, true, compiler_option: :freezing
# Build ECMAScript modules, instead of legacy JS
#
# @return [true, false]
config_option :esm, false, compiler_option: :esm
# Set the error severity for when a require can't be parsed at compile time.
#
# @example
# # Opal code
# require "foo" + some_dynamic_value
#
# - `:error` will raise an error at compile time
# - `:warning` will print a warning on stderr at compile time
# - `:ignore` will skip the require silently at compile time
#
# @return [:error, :warning, :ignore]
config_option :dynamic_require_severity, :warning, compiler_option: :dynamic_require_severity, valid_values: %i[error warning ignore]
# Set the error severity for when a required file can't be found at build time.
#
# @example
# # Opal code
# require "some_non_existen_file"
#
# - `:error` will raise an error at compile time
# - `:warning` will print a warning on stderr at compile time
# - `:ignore` will skip the require silently at compile time
#
# @return [:error, :warning, :ignore]
config_option :missing_require_severity, :error, valid_values: %i[error warning ignore]
# Enable IRB support for making local variables across multiple compilations.
#
# @return [true, false]
config_option :irb_enabled, false, compiler_option: :irb
# Enable for inline operators optimizations.
#
# @return [true, false]
config_option :inline_operators_enabled, true, compiler_option: :inline_operators
# Enable source maps support.
#
# @return [true, false]
config_option :source_map_enabled, true
# Enable source location embedded for methods and procs.
#
# @return [true, false]
config_option :enable_source_location, false, compiler_option: :enable_source_location
# Enable embedding source code to be read by applications.
#
# @return [true, false]
config_option :enable_file_source_embed, false, compiler_option: :enable_file_source_embed
# A set of stubbed files that will be marked as loaded and skipped during
# compilation. The value is expected to be mutated but it's ok to replace
# it.
#
# @return [Set]
config_option :stubbed_files, -> { Set.new }, valid_values: [Set]
end
end