github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/natives/src/crypto/rand/rand.go (about)

     1  //go:build js
     2  // +build js
     3  
     4  package rand
     5  
     6  import (
     7  	"errors"
     8  
     9  	"github.com/gopherjs/gopherjs/js"
    10  )
    11  
    12  type reader struct{}
    13  
    14  func (r *reader) Read(b []byte) (n int, err error) {
    15  	array := js.InternalObject(b).Get("$array")
    16  	offset := js.InternalObject(b).Get("$offset").Int()
    17  
    18  	// browser
    19  	crypto := js.Global.Get("crypto")
    20  	if crypto == js.Undefined {
    21  		crypto = js.Global.Get("msCrypto")
    22  	}
    23  	if crypto != js.Undefined {
    24  		if crypto.Get("getRandomValues") != js.Undefined {
    25  			n = len(b)
    26  			if n > 65536 {
    27  				// Avoid QuotaExceededError thrown by getRandomValues
    28  				// when length is more than 65536, as specified in
    29  				// http://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
    30  				n = 65536
    31  			}
    32  			crypto.Call("getRandomValues", array.Call("subarray", offset, offset+n))
    33  			return n, nil
    34  		}
    35  	}
    36  
    37  	// Node.js
    38  	if require := js.Global.Get("require"); require != js.Undefined {
    39  		if randomBytes := require.Invoke("crypto").Get("randomBytes"); randomBytes != js.Undefined {
    40  			array.Call("set", randomBytes.Invoke(len(b)), offset)
    41  			return len(b), nil
    42  		}
    43  	}
    44  
    45  	return 0, errors.New("crypto/rand not available in this environment")
    46  }