This is a snippet for the code that I want to do Blob to Base64 string:
This commented part works and that when the URL generated by this is set to img src it displays the image:
var blob = items[i].getAsFile();
//var URLObj = window.URL || window.webkitURL;
//var source = URLObj.createObjectURL(blob);
//console.log("image source=" + source);
var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result)
}; // data url!
var source = reader.readAsBinaryString(blob);
The problem is with the the lower code, the source variable generated is null
Update:
Is there an easier way to do this with JQuery to be able to create Base64 String from Blob file as in the code above?
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
var base64data = reader.result;
console.log(base64data);
}
Form the docs readAsDataURL encodes to base64
As an awaitable function:
function blobToBase64(blob) {
return new Promise((resolve, _) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
Note: The blob's result cannot be directly decoded as Base64 without first removing the Data-URL declaration preceding the Base64-encoded data. To retrieve only the Base64 encoded string, first remove data:/;base64, from the result.
this worked for me:
var blobToBase64 = function(blob, callback) {
var reader = new FileReader();
reader.onload = function() {
var dataUrl = reader.result;
var base64 = dataUrl.split(',')[1];
callback(base64);
};
reader.readAsDataURL(blob);
};
There is a pure JavaScript way that is not depended on any stacks:
const blobToBase64 = blob => {
const reader = new FileReader();
reader.readAsDataURL(blob);
return new Promise(resolve => {
reader.onloadend = () => {
resolve(reader.result);
};
});
};
For using this helper function you should set a callback, example:
blobToBase64(blobData).then(res => {
// do what you wanna do
console.log(res); // res is base64 now
});
I write this helper function for my problem on React Native project, I wanted to download an image and then store it as a cached image:
fetch(imageAddressAsStringValue)
.then(res => res.blob())
.then(blobToBase64)
.then(finalResult => {
storeOnMyLocalDatabase(finalResult);
});
var audioURL = window.URL.createObjectURL(blob);
audio.src = audioURL;
var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
base64data = reader.result;
console.log(base64data);
}
function bufferToBinaryString(arrayBuffer){
return String.fromCharCode(...new Uint8Array(arrayBuffer));
}
(async () => console.log(btoa(bufferToBinaryString(await new Response(blob).arrayBuffer()))))();
or
function bufferToBinaryString(arrayBuffer){
return String.fromCharCode(...new Uint8Array(arrayBuffer));
}
new Response(blob).arrayBuffer().then(arr_buf => console.log(btoa(bufferToBinaryString(arr_buf)))))
see Response's constructor, you can turn [blob, buffer source form data, readable stream, etc.] into Response, which can then be turned into [json, text, array buffer, blob] with async method/callbacks.
edit: as #Ralph mentioned, turning everything into utf-8 string causes problems (unfortunately Response API doesn't provide a way converting to binary string), so array buffer is use as intermediate instead, which requires two more steps (converting it to byte array THEN to binary string), if you insist on using native btoa method.
So the problem is that you want to upload a base 64 image and you have a blob url. Now the answer that will work on all html 5 browsers is:
Do:
var fileInput = document.getElementById('myFileInputTag');
var preview = document.getElementById('myImgTag');
fileInput.addEventListener('change', function (e) {
var url = URL.createObjectURL(e.target.files[0]);
preview.setAttribute('src', url);
});
function Upload()
{
// preview can be image object or image element
var myCanvas = document.getElementById('MyCanvas');
var ctx = myCanvas.getContext('2d');
ctx.drawImage(preview, 0,0);
var base64Str = myCanvas.toDataURL();
$.ajax({
url: '/PathToServer',
method: 'POST',
data: {
imageString: base64Str
},
success: function(data) { if(data && data.Success) {}},
error: function(a,b,c){alert(c);}
});
}
async function blobToBase64(blob) {
return new Promise((resolve, _) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
let blob = null; // <= your blob object goes here
blobToBase64(blob)
.then(base64String => console.log(base64String));
See also:
https://gist.github.com/moosetraveller/723987931308c9ec63725c14cdcbc3e7
you can fix problem by:
var canvas = $('#canvas');
var b64Text = canvas.toDataURL();
b64Text = b64Text.replace('data:image/png;base64,','');
var base64Data = b64Text;
I hope this help you
async TypeScript variation:
async function blobToBase64Async(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onerror = (e) => reject(fileReader.error);
fileReader.onloadend = (e) => {
const dataUrl = fileReader.result as string;
// remove "data:mime/type;base64," prefix from data url
const base64 = dataUrl.substring(dataUrl.indexOf(',') + 1);
resolve(base64);
};
fileReader.readAsDataURL(blob);
});
}
Sample usage:
async function fetchToBase64Async(url: string, init?: RequestInit): Promise<string> {
try {
const response = await fetch(url, init);
if (!response.ok) {
const responseText = await response.text();
throw new Error("server status: " + response.status + "\n" + "server response:" + "\n" + responseText);
}
const blob = await response.blob();
const base64 = await blobToBase64Async(blob);
return base64;
} catch (e) {
throw new Error("failed to fetch: " + url + "\n" + "caused by: " + e);
}
}
async function demoUsage() {
const base64 = await fetchToBase64Async("https://httpstat.us/200", {
method: "POST",
headers: {
"Accept": "*/*",
"Authorization": "Bearer ...",
}
});
console.log(base64);
}
Notes:
I don't understand why some answers use the load instead of the loadend event
I don't understand why some answers call readAsDataURL before setting the event handler
Another way is to use a simple wrapper around FileReader returning Observable (snippet is in TypeScript):
function toBase64(blob: Blob): Observable<string> {
const reader = new FileReader();
reader.readAsDataURL(blob);
return fromEvent(reader, 'load')
.pipe(map(() => (reader.result as string).split(',')[1]));
}
Usage:
toBase64(blob).subscribe(base64 => console.log(base64));
The answer from #Arun Killu is a good snippet if you know what is going on, but nobody has explained what was the error on the original code. For people using async and Promise calls this is error is soo obvious but for people learning or without experience it's not so clear.
Here a simple explanation.
The Bad code
var blob = items[i].getAsFile();
var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result)
}; // data url!
var source = reader.readAsBinaryString(blob);
Above code is trying to capture a binary string on source variable, however, FileReader.readAsBinaryString() returns undefined. This is because the result will be available whenever the event onload will be triggered. As we can see, he was trying to console.log the event.target.result value, which is a wrong approach.
The Good code
Here is a step by step implementation:
// 1. Create a FileReader instance
const reader = new FileReader()
// 2. Add a handler for the 'onload' event
reader.onload = (e) => {
// 5. Get the result when the 'onload' event is triggered.
const base64data = reader.result
console.log({base64data})
}
// 3. Add a handler for the 'onerror' event
reader.onerror = () => {
console.log('error')
}
// 4. Call 'readAsDataURL' method
reader.readAsDataURL(imageBlob)
As you can see the last step is 5 and it is because it is an asynchronous call.
Here is a working example:
const url = 'https://i.stack.imgur.com/RRuCp.png'
const fetchImage = async url => {
const response = await fetch(url, {mode: 'no-cors',})
const blob = await response.blob()
return blob
}
const loadImage = async () => {
const imageBlob = await fetchImage(url)
const reader = new FileReader()
reader.onload = () => {
const base64data = reader.result
console.log({base64data})
}
reader.onerror = () => {
console.log('error')
}
reader.readAsDataURL(imageBlob)
}
loadImage()
Teo, what means asynchronous?
Well young Padawan, asynchronous means that we don't know when the result will be ready, it can be different in each system and depends on how heavy or complex is the process and also it can find some errors that will not produce any result at all.
So if a process is asynchronous is a good practice to encapsulate it using an async method and returning a Promise like this:
const blobToBase64 = async blob => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result)
reader.error = (err) => reject(err)
reader.readAsDataURL(blob)
})
}
Ah okay Teo, but what is a Promise?
Good question my young fella. A Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value. In other words, will tell us if the result is ready and will give us its value, otherwise will return an error.
Above code shows a function blobToBase64 that will return a Promise This means that this function will return reader.result when it ready.
How can we integrate it into our code?
Super easy, just replace all the FileReader with the function blobToBase64 defined above and call it like this imageBase64 = await blobToBase64(imageBlob)
Check this snippet:
const url = 'https://i.stack.imgur.com/RRuCp.png'
const fetchImage = async url => {
const response = await fetch(url, {
mode: 'no-cors',
})
const blob = await response.blob()
return blob
}
const blobToBase64 = async blob => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result)
reader.error = (err) => reject(err)
reader.readAsDataURL(blob)
})
}
const loadImage = async() => {
const imageBlob = await fetchImage(url)
const imageBase64 = await blobToBase64(imageBlob)
console.log({imageBase64})
}
loadImage()
Typescript version :
const blob2Base64 = (blob:Blob):Promise<string> => {
return new Promise<string> ((resolve,reject)=> {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => resolve(reader.result.toString());
reader.onerror = error => reject(error);
})
}
usage:
blob2Base64(blob).then(res=>console.log(res))
Maybe I'm missing something but
let encoded = btoa(await myblob.text());
... is all you need to do to encode a Blob's data to base64. See Blob.text() and btoa().
Or if you want the whole thing as a promise:
let encode = myblob.text().then(btoa);
PS: To decode back to a Blob: new Blob([atob(encoded)])
I wanted something where I have access to base64 value to store into a list and for me adding event listener worked. You just need the FileReader which will read the image blob and return the base64 in the result.
createImageFromBlob(image: Blob) {
const reader = new FileReader();
const supportedImages = []; // you can also refer to some global variable
reader.addEventListener(
'load',
() => {
// reader.result will have the required base64 image
const base64data = reader.result;
supportedImages.push(base64data); // this can be a reference to global variable and store the value into that global list so as to use it in the other part
},
false
);
// The readAsDataURL method is used to read the contents of the specified Blob or File.
if (image) {
reader.readAsDataURL(image);
}
}
Final part is the readAsDataURL which is very important is being used to read the content of the specified Blob
If your "blob" is an actual Blob Object and not a blob url, the conversion is pretty simple:
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = () => resolve(reader.result)
example of Blob Object:
console.log(blob)
output:
Blob {lastModified: 1658039931443, lastModifiedDate: Sun Jul 17 2022 08:38:51 GMT+0200 (Central European Summer Time), name: '1.jpg', size: 35493, type: 'image/jpeg'}
lastModified: 1658039931443
lastModifiedDate: Sun Jul 17 2022 08:38:51 GMT+0200 (Central European Summer Time) {}
name: "1.jpg"
size: 35493
type: "image/jpeg"
[[Prototype]]: Blob
In my case, the blob was produced by Compressorjs (should you need image compression).
Related
I've been trying to find a way to Base64 encode binary data with JavaScript for the past few hours and it turns out that btoa() only works with strings so I came up with the following code, where blob is the file I need to encode:
function base64Encode(blob) {
var reader = new FileReader();
reader.readAsDataURL(blob)
reader.onloadend = function() {
console.log(reader.result);
};
};
Problem is, base64Encode(blob) always returns undefined, does anybody know a fix?
You are not returning anything from your function, you could use promises and async/await. As an example see the below code, it might help you.
const convertBlobToBase64 = async (blob) => {
return await blobToBase64(blob);
}
const blobToBase64 = blob => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
caller:
console.log(await convertBlobToBase64(someFileData));
I have this function where I call a function and have a local file as the parameter to convert it to base64.
export const fileToBase64 = (filename, filepath) => {
return new Promise(resolve => {
var file = new File([filename], filepath);
var reader = new FileReader();
// Read file content on file loaded event
reader.onload = function(event) {
resolve(event.target.result);
};
// Convert data to base64
reader.readAsDataURL(file);
});
}
Importing the function
fileToBase64("shield.png", "./form").then(result => {
console.log(result);
console.log("here");
});
gives me an output as
data:application/octet-stream;base64,c2hpZWxkLnBuZw==
here
I want base64 information, but noticing the file the application/octet-stream is wrong? I entered an image so shouldn't it be
data:image/pgn;base64,c2hpZWxkLnBuZw==
https://medium.com/#simmibadhan/converting-file-to-base64-on-javascript-client-side-b2dfdfed75f6
try this I think this should helpfull
let buff = new Buffer(result, 'base64');
let text = buff.toString('ascii');
console.log(text)
So I am trying to convert a file from tag. This is how my javascript code looks like:
var file = document.getElementById("file").files[0];
if (file) {
var filereader = new FileReader();
filereader.readAsDataURL(file);
filereader.onload = function (evt) {
var base64 = evt.target.result;
}
}
That returns undefined.
two little helper and an example.
const blobToDataUrl = blob => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
const blobToBase64 = blob => blobToDataUrl(blob).then(text => text.slice(text.indexOf(",")));
for(let file of document.getElementById("file").files) {
blobToBase64(file).then(base64 => console.log(file, base64));
}
But why the Promises?
Because your next question will be: How do I get the base64 string out of onload? and the short answer is You don't. A longer answer would be: It's like asking how to get something from the future into the now. You can't.
Promises are placeholder/wrapper for values that will eventually be available; but not yet. And they are the foundation of async functions.
So let's skip messing with callbacks and get right to the point where you write
for(let file of document.getElementById("file").files) {
const base64 = await blobToBase64(file);
console.log(file, base64);
}
but for that you will have to brush up on async and await.
I think you have missed the return statement in the code.
Replace your function with the following lines:
var file = document.getElementById("file").files[0];
if (file) {
var filereader = new FileReader();
filereader.readAsDataURL(file);
filereader.onload = function (evt) {
var base64 = evt.target.result;
return base64
}
}
Reference: FileReader.readAsDataURL
Considering the following example:
function previewFile(file) {
var reader = new FileReader();
reader.onloadend = function () {
console.log(reader.result);
}
reader.readAsDataURL(file);
}
It states:
instanceOfFileReader.readAsDataURL(blob);
blob: The Blob or File from which to read.
How can a local file URL like: 'file:///C:/path-to/root.png' be
passed to the readAsDataURL()
Is FileReader() available in a Firefox Addon?
To convert a URL to a Blob for FileReader.readAsDataURL() do this:
var request = new XMLHttpRequest();
request.open('GET', MY_URL, true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
console.log('DataURL:', e.target.result);
};
};
request.send();
Expanding on Felix Turner s response, here is how I would use this approach with the fetch API.
async function createFile(){
let response = await fetch('http://127.0.0.1:8080/test.jpg');
let data = await response.blob();
let metadata = {
type: 'image/jpeg'
};
let file = new File([data], "test.jpg", metadata);
// ... do something with the file or return it
}
createFile();
The suggested edit queue is full for #tibor-udvari's excellent fetch answer, so I'll post my suggested edits as a new answer.
This function gets the content type from the header if returned, otherwise falls back on a settable default type.
async function getFileFromUrl(url, name, defaultType = 'image/jpeg'){
const response = await fetch(url);
const data = await response.blob();
return new File([data], name, {
type: data.type || defaultType,
});
}
// `await` can only be used in an async body, but showing it here for simplicity.
const file = await getFileFromUrl('https://example.com/image.jpg', 'example.jpg');
Try this I learned this from #nmaier when I was mucking around with converting to ico:
Well i dont really understand what array buffer is but it does what we need:
function previewFile(file) {
var reader = new FileReader();
reader.onloadend = function () {
console.log(reader.result); //this is an ArrayBuffer
}
reader.readAsArrayBuffer(file);
}
notice how i just changed your readAsDataURL to readAsArrayBuffer.
Here is the example #nmaier gave me:
https://stackoverflow.com/a/24253997/1828637
it has a fiddle
if you want to take this and make a file out of it i would think you would use file-output-stream in the onloadend
This information is outdated as of now, but cannot be deleted.
You can create File instances just by specifying a path when your code is chrome-privileged:
new File("/path/to/file");
File is a sub-class of Blob, so all File instances are also valid Blobs.
Please note that this requires a platform path, and not a file URL.
Yes, FileReader is available to addons.
File and FileReader are available in all windows. If you want to use them in a non-window scope (like bootstrap.js or a code module), you may use nsIDOMFile/nsIDOMFileReader.
Here is my code using async awaits and promises
const getBlobFromUrl = (myImageUrl) => {
return new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open('GET', myImageUrl, true);
request.responseType = 'blob';
request.onload = () => {
resolve(request.response);
};
request.onerror = reject;
request.send();
})
}
const getDataFromBlob = (myBlob) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(myBlob);
})
}
const convertUrlToImageData = async (myImageUrl) => {
try {
let myBlob = await getBlobFromUrl(myImageUrl);
console.log(myBlob)
let myImageData = await getDataFromBlob(myBlob);
console.log(myImageData)
return myImageData;
} catch (err) {
console.log(err);
return null;
}
}
export default convertUrlToImageData;
I know this is an expansion off of #tibor-udvari's answer, but for a nicer copy and paste.
async function createFile(url, type){
if (typeof window === 'undefined') return // make sure we are in the browser
const response = await fetch(url)
const data = await response.blob()
const metadata = {
type: type || 'video/quicktime'
}
return new File([data], url, metadata)
}
I ended up wanting something similar to this but without having to pass the type for the file or the filename, so I made my own example based on #Felix Turner's example. I used the content-disposition header for the filename first in case the file is coming back from an API endpoint, but use the last part of the URL path if that header doesn't exist.
function getFilenameFromContentDisposition(res) {
let filename = null;
const disposition = res.headers.get("content-disposition");
if (disposition?.includes("attachment")) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches?.[1]) {
filename = matches[1].replace(/['"]/g, "");
// Sometimes the filename comes in a URI encoded format so decode it
filename = decodeURIComponent(filename);
// Sometimes the filename starts with UTF-8, remove that
filename = filename.replace(/^UTF-8/i, "").trim();
}
}
return filename;
}
async function getFileFromLink(url) {
const fileRes = await fetch(url);
const blob = await fileRes.blob();
let fileName = getFilenameFromContentDisposition(fileRes);
if (!fileName) {
fileName = url.split("/").pop();
}
const file = new File([blob], fileName, {
type: blob.type,
});
return file;
}
If you wanted to make this better, I'd use the content-disposition package on npm for the parsing as the formatting of it can get strange. I'd also probably use the mime package for ensuring that the filename from the URL has a proper file extension based on the returned content-type
Here's a simplest way to get blob or file object with vanila.js and promise
const fileURL_to_blob = (file_url) => {
return new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open('GET', file_url, true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
//console.log('DataURL:', e.target.result);
resolve(e.target.result);
};
};
request.onerror=function(e){
reject(e);
}
request.send();
});
}
I was studying Blobs, and I noticed that when you have an ArrayBuffer, you can easily convert this to a Blob as follows:
var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });
The question I have now is, is it possible to go from a Blob to an ArrayBuffer?
You can use FileReader to read the Blob as an ArrayBuffer.
Here's a short example:
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
Here's a longer example:
// ArrayBuffer -> Blob
var uint8Array = new Uint8Array([1, 2, 3]);
var arrayBuffer = uint8Array.buffer;
var blob = new Blob([arrayBuffer]);
// Blob -> ArrayBuffer
var uint8ArrayNew = null;
var arrayBufferNew = null;
var fileReader = new FileReader();
fileReader.onload = function(event) {
arrayBufferNew = event.target.result;
uint8ArrayNew = new Uint8Array(arrayBufferNew);
// warn if read values are not the same as the original values
// arrayEqual from: http://stackoverflow.com/questions/3115982/how-to-check-javascript-array-equals
function arrayEqual(a, b) { return !(a<b || b<a); };
if (arrayBufferNew.byteLength !== arrayBuffer.byteLength) // should be 3
console.warn("ArrayBuffer byteLength does not match");
if (arrayEqual(uint8ArrayNew, uint8Array) !== true) // should be [1,2,3]
console.warn("Uint8Array does not match");
};
fileReader.readAsArrayBuffer(blob);
fileReader.result; // also accessible this way once the blob has been read
This was tested out in the console of Chrome 27—69, Firefox 20—60, and Safari 6—11.
Here's also a live demonstration which you can play with: https://jsfiddle.net/potatosalad/FbaM6/
Update 2018-06-23: Thanks to Klaus Klein for the tip about event.target.result versus this.result
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsArrayBuffer()
https://www.w3.org/TR/FileAPI/#dfn-readAsArrayBuffer
The Response API consumes a (immutable) Blob from which the data can be retrieved in several ways. The OP only asked for ArrayBuffer, and here's a demonstration of it.
var blob = GetABlobSomehow();
// NOTE: you will need to wrap this up in a async block first.
/* Use the await keyword to wait for the Promise to resolve */
await new Response(blob).arrayBuffer(); //=> <ArrayBuffer>
alternatively you could use this:
new Response(blob).arrayBuffer()
.then(/* <function> */);
Note: This API isn't compatible with older (ancient) browsers so take a look to the Browser Compatibility Table to be on the safe side ;)
Or you can use the fetch API
fetch(URL.createObjectURL(myBlob)).then(res => res.arrayBuffer())
I don't know what the performance difference is, and this will show up on your network tab in DevTools as well.
Just to complement Mr #potatosalad answer.
You don't actually need to access the function scope to get the result on the onload callback, you can freely do the following on the event parameter:
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
Why this is better? Because then we may use arrow function without losing the context
var fileReader = new FileReader();
fileReader.onload = (event) => {
this.externalScopeVariable = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
This is an async method which first checks for the availability of arrayBuffer method. This function is backward compatible and future proof.
async function blobToArrayBuffer(blob) {
if ('arrayBuffer' in blob) return await blob.arrayBuffer();
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject();
reader.readAsArrayBuffer(blob);
});
}
await blob.arrayBuffer() is good.
The problem is when iOS / Safari support is needed.. for that one would need this:
Blob.prototype.arrayBuffer ??=function(){ return new Response(this).arrayBuffer() }
There is now (Chrome 76+ & FF 69+) a Blob.prototype.arrayBuffer() method which will return a Promise resolving with an ArrayBuffer representing the Blob's data.
(async () => {
const blob = new Blob(['hello']);
const buf = await blob.arrayBuffer();
console.log( buf.byteLength ); // 5
})();