Here is a sample code

$$$ThrowOnError(tUtils.CreateCMSStream(tContent,tCertFileName, tKeyFileName, tPassPhrase, .tStream)) //the stream is initialized in CreateCMSStream
     zwrite tStream
     set tStream.Filename = "C:\Users\sdevin\Documents\DEV\iris-pkcs7-util\misc\out\test.cms"
     set tsc = tStream.%Save()
     zw tsc
     zw tsc2
     zwrite tStream

And here is where I create the stream

Method ConvertStringToStream(pString, Output pStream As %Stream.FileBinary) As %Status
{
     set pStream = ##class(%Stream.FileBinary).%New()
     do pStream.Write(pString)
     do pStream.Rewind()
     return pStream
}

convertStreamToString is the last instruction of CreateCMSStream

I have done it 😁 it need some polish but here is the code to accomplish it using the %SyntaxColor library:

Method ExtractJsFunctionBody(jsCodePath As %String, fnName As %String)
{
  
    #; Reading from a file, writing to a temporary stream
   set syn = ##class(%SyntaxColor).%New(), in = ##class(%Stream.FileCharacter).%New(), out = ##class(%Stream.TmpCharacter).%New()
    // set js content in content var    
   set content = in.Read($$$MaxStringLength)
   do InStream.Rewind()
   #; Need the "K" flag to get JSON output
   do in.LinkToFile(jsCodePath), syn.Color(in,out,"JS","K")
   #; Get a %DynamicArray from the stream
   set lines = ##class(%DynamicArray).%FromJSON(out)
   // get list by line of jsCode
   set lineList = $listfromstring(content, $char(10))

   // get pos and line of function def begining 
   set iterLines = lines.%GetIterator()
   while iterLines.%GetNext(.linenumber , .line, .type) {

      set value = line.%Get(1)
      if ((value.%Get("s") = 16) &&  (value.%Get("c") = 8)){  
         set value = line.%Get(3)
         if (value.%Get("s") = 14 ){
            set tempFnName = $extract($list(lineList, linenumber + 1),value.%Get("p") + 1, value.%Get("p") + value.%Get("c"))
            if (tempFnName = fnName ){
               set functionLineBegin = linenumber + 1
               quit
            }
         }
      }
   }
   
   // get pos of function def ending
   set functionLineEnd = ..braketCounter(iterLines, lineList)
   
   //extract functiun Body
   set functionBody = $listtostring($list(lineList,functionLineBegin,functionLineEnd),$char(10))
   write !!!, functionBody
}

/// Count braket and return the line of the corresponding ending one take an iterrator at the line of the begining of the search and a list of the lines
Method braketCounter(iterLines As %Iterator.AbstractIterator, lineList As %DynamicArray) As %Integer
{
   set countBraket = 1
   while iterLines.%GetNext(.linenumber , .line, .type) { // we keep the same iterator to continue from where we where
      set iterTokens = line.%GetIterator()
      while iterTokens.%GetNext(.key , .value, .type){
         set token = $extract($list(lineList, linenumber + 1),value.%Get("p") + 1, value.%Get("p") + value.%Get("c") )
         if (value.%Get("s") = 4) {
            if (  token = "{"){
               set countBraket = countBraket + 1}
            elseif ( token = "}"){
               set countBraket = countBraket - 1}
            if (countBraket = 0){
               return linenumber 
            }
         }
         
      }
   }
   return "error"
}

after some testing I found out that multiple token have the same attribute number
As I haven't found documentation about wich token is wich attribute number I put it here.

what i found out for wich attribute number equal to wich JS token :
1 : new line or blank space / tabulation
2 : no occurence in my file
3 : no occurence in my file
4 : ( ) [ ] { } ; , : .
5 : " '
6 : comment //
7 : number
8 : no occurence in my file
9: no occurence in my file 
10 : / single slash (probably to delimit regEx)
11 : ^ + | $ (in regEx)
12 : \s (maybe escaped char in regEx)
13 : g (maybe the mode of a regEx)
14 : variable, function name (call and def)
15 :  =
16 : function and var keywords
and I stopped here.