# frozen_string_literal: truerequire'opal/rewriters/base'moduleOpalmoduleRewriters# This module attempts to run some optimizations or compatibility# improvements against some libraries used with Opal.## This should be a last resort and must not break functionality in# existing applications.classTargetedPatches<Basedefon_def(node)name,args,body=*nodeifbody&&body.type==:begin&&body.children.length>=2# parser/rubyxx.rb - racc generated code often looks like:## def _reduce_219(val, _values, result)# result = @builder.op_assign(val[0], val[1], val[2])# result# end## This converter transform this into just## def _reduce_219(val, _values, result)# @builder.op_assign(val[0], val[1], val[2])# endcalls=body.childrenassignment,ret=calls.last(2)ifassignment.type==:lvasgn&&ret.type==:lvar&&assignment.children.first==ret.children.firstifcalls.length==2node.updated(nil,[name,args,assignment.children[1]])elsecalls=calls[0..-3]<<assignment.children[1]node.updated(nil,[name,args,body.updated(nil,calls)])endelsesuperendelsesuperendenddefon_array(node)children=node.children# Optimize large arrays produced by lexer, but mainly we are interested# in improving compile times, by reducing the tree for the further# compilation efforts (also reducing the bundle size a bit)## This particular patch reduces compile time of the following command# by 12.5%:## OPAL_CACHE_DISABLE=true OPAL_PREFORK_DISABLE=true bin/opal \# --no-source-map -ropal-parser -ropal/platform -ce \# 'puts ::Opal.compile($stdin.read)' > _Cnow.js## So, in short, an array of a kind:## [1, 2, 3, nil, nil, :something, :abc, nil, ...]## Becomes compiled to:## Opal.large_array_unpack("1,2,3,,something,abc,,...")ifchildren.length>32ssin_array=children.all?do|child|# Break for wrong typesnextfalseunless%i[str sym int nil].include?(child.type)# Break for strings that may conflict with our numbers, nils and separatornextfalseif%i[str sym].include?(child.type)&&child.children.first.to_s=~/\A[0-9-]|\A\z|,/# Break for too numbers out of range, as there may be decoding issuesnextfalseifchild.type==:int&&!(-1_000_000..1_000_000).cover?(child.children.first)trueendifssin_arraystr=children.map{|i|i.children.first.to_s}.join(',')node.updated(:jscall,[s(:js_tmp,:Opal),:large_array_unpack,s(:sym,str)])elsesuperendelsesuperendendendendend