class Object
Public Instance Methods
Polyfill(options = {})
click to toggle source
Calls superclass method
# File lib/polyfill.rb, line 66 def Polyfill(options = {}) # rubocop:disable Naming/MethodName # # parse options # objects, others = options.partition { |key,| key[/\A[A-Z]/] } objects.sort! do |a, b| if !a.is_a?(Class) && b.is_a?(Class) -1 elsif a.is_a?(Class) && !b.is_a?(Class) 1 else 0 end end objects.each do |object_name, _| Object.const_get(object_name.to_s, false) end others = others.to_h versions = Polyfill::InternalUtils.polyfill_versions_to_use(others.delete(:version)) native = others.delete(:native) { false } unless others.empty? raise ArgumentError, "unknown keyword: #{others.first[0]}" end # # build the module to return # Polyfill::InternalUtils.create_module(options) do |mod| objects.each do |object_name, methods| # # find all polyfills for the object across all versions # modules_with_updates, instance_modules = Polyfill::InternalUtils.modules_to_use(object_name, versions) class_modules_with_updates = modules_with_updates.map do |module_with_updates| begin module_with_updates.const_get(:ClassMethods, false) rescue NameError nil end end.compact class_modules = instance_modules.map do |module_with_updates| begin module_with_updates.const_get(:ClassMethods, false).clone rescue NameError nil end end.compact # # get all requested class and instance methods # if methods != :all && (method_name = methods.find { |method| method !~ /\A[.#]/ }) raise ArgumentError, %Q("#{method_name}" must start with a "." if it's a class method or "#" if it's an instance method) end instance_methods, class_methods = if methods == :all %i[all all] else methods .partition { |m| m.start_with?('#') } .map { |method_list| method_list.map { |name| name[1..-1].to_sym } } end requested_instance_methods = Polyfill::InternalUtils.methods_to_keep(modules_with_updates, instance_methods, '#', object_name) requested_class_methods = Polyfill::InternalUtils.methods_to_keep(class_modules_with_updates, class_methods, '.', object_name) # # get the class(es) to refine # base_object = object_name.to_s base_objects = case base_object when 'Comparable' %w[Numeric String Time] when 'Enumerable' %w[Array Dir Enumerator Hash IO Matrix Range StringIO Struct Vector] when 'Kernel' %w[Object] else [base_object] end base_objects.select! do |klass| begin Object.const_get(klass, false) rescue NameError false end end # # refine in class methods # class_modules.each do |class_module| Polyfill::InternalUtils.keep_only_these_methods!(class_module, requested_class_methods) next if class_module.instance_methods.empty? mod.module_exec(requested_class_methods) do |methods_added| base_objects.each do |klass| refine Object.const_get(klass, false).singleton_class do include class_module if native Polyfill::InternalUtils.ignore_warnings do define_method :respond_to? do |name, include_all = false| return true if methods_added.include?(name) super(name, include_all) end define_method :__send__ do |name, *args, &block| return super(name, *args, &block) unless methods_added.include?(name) class_module.instance_method(name).bind(self).call(*args, &block) end alias_method :send, :__send__ end end end end end end # # refine in instance methods # instance_modules.each do |instance_module| Polyfill::InternalUtils.keep_only_these_methods!(instance_module, requested_instance_methods) next if instance_module.instance_methods.empty? mod.module_exec(requested_instance_methods) do |methods_added| base_objects.each do |klass| refine Object.const_get(klass, false) do include instance_module # Certain Kernel methods are private outside of Kernel if klass == 'Object' %i[Complex Float Integer Rational].each do |method| private method if methods_added.include?(method) end end if native Polyfill::InternalUtils.ignore_warnings do define_method :respond_to? do |name, include_all = false| return super(name, include_all) unless methods_added.include?(name) true end define_method :__send__ do |name, *args, &block| return super(name, *args, &block) unless methods_added.include?(name) instance_module.instance_method(name).bind(self).call(*args, &block) end alias_method :send, :__send__ end end end end end end end end end