This article is a continuation of the article below.
Please see the article about Javet the other day.
Modification of loadWithGlobalPool function
Add engine and returnVar to the parameters. Below is a sample.
var pdfDataUri=loadWithGlobalPool({
name:"pdf-lib-javet",
max:10,
initializer:initscript,
script:runscript,
context:{bytesIPAexgothic:bytesIPAexgothic,createdate:new Date().format("mm:ss SSS")},
engine:"javet",
returnVar:"pdfDataUri",
});
Last time, we used the Nashorn engine's multi-context support mechanism to create a pool with multiple contexts and to be able to handle multiple requests at the same time. This time, I would like to use Javet. Since we need to switch between Nashorn and Javet, we will set an engine parameter.
Also, Javet's await is a standard specification of ES2017 and can only be used within async functions and cannot be called at the TOP level. And, like Nashorn's extended await function from last time, it cannot be executed at the TOP level and wait for the Promise execution result. In order to obtain the execution result of the Promise, it is necessary to specify which variable will become the result after execution is completed. This is the reason for creating returnVar.
pdf-lib test source
- global.js
var global={};
var bytesIPAexgothic=null;
global.fire=function(){
bytesIPAexgothic=file.readAllBytes("font/ipaexg00401.ttf");
efw.register("bytesIPAexgothic");
}
- testJavet.js
var testJavet={};
testJavet.paramsFormat={
pdf:null
};
testJavet.fire=function(params){
var initscript=`
const PDFLib = require(_eventfolder+"/pdf-lib.min.js");
const fontkit = require(_eventfolder+"/fontkit.umd.min.js");
function byteToUint8Array(byteArray) {
var uint8Array = new Uint8Array(byteArray.length);
uint8Array.set(Array.from(byteArray));
return uint8Array;
}
var embedderIPAexgothic;
(async function(){
embedderIPAexgothic=await PDFLib.CustomFontSubsetEmbedder.for(
fontkit,
byteToUint8Array(bytesIPAexgothic),
"IPAexゴシック",
{}
);
})();
`;
var runscript=`
var pdfDataUri;
(async function(){
var pdfDoc=await PDFLib.PDFDocument.create();
var myfont=PDFLib.PDFFont.of(pdfDoc.context.nextRef(), pdfDoc, embedderIPAexgothic);
pdfDoc.fonts.push(myfont);
var page = pdfDoc.addPage([500, 400]);
page.setFont(myfont);
page.moveTo(10, 200);
page.drawText('Hello World!こんにちは東京'+createdate);
pdfDataUri=await pdfDoc.saveAsBase64({ dataUri: true });
})();
`;
var pdfDataUri=loadWithGlobalPool({
name:"pdf-lib-javet",
max:10,
initializer:initscript,
script:runscript,
context:{bytesIPAexgothic:bytesIPAexgothic,createdate:new Date().format("mm:ss SSS")},
engine:"javet",
returnVar:"pdfDataUri",
});
return new Result().eval("$('"+params.pdf+"')[0].src='" +pdfDataUri +"'");
}
The way to write the source is quite similar to the previous Nashorn version, but the way to write the await-related parts is different. This is the standard ES2017 way of writing. I feel like the await function of the Nashorn extension from last time is easier to understand. For comparison, I'll paste here how to write the Nashorn extension.
- testNashorn.js
var testNashorn={};
testNashorn.paramsFormat={
pdf:null
};
testNashorn.fire=function(params){
var initscript=`
load(_eventfolder+"/pdf-lib.min.js");
load(_eventfolder+"/fontkit.umd.min.js");
function byteToUint8Array(byteArray) {
var uint8Array = new Uint8Array(byteArray.length);
uint8Array.set(Java.from(byteArray));
return uint8Array;
}
var embedderIPAexgothic=await(PDFLib.CustomFontSubsetEmbedder.for(
fontkit,
byteToUint8Array(bytesIPAexgothic),
"IPAexゴシック",
{}
)
);
`;
var runscript=`
var pdfDataUri;
var pdfDoc=await(PDFLib.PDFDocument.create());
var myfont=PDFLib.PDFFont.of(pdfDoc.context.nextRef(), pdfDoc, embedderIPAexgothic);
pdfDoc.fonts.push(myfont);
var page = pdfDoc.addPage([500, 400]);
page.setFont(myfont);
page.moveTo(10, 200);
page.drawText('Hello World!こんにちは東京'+createdate);
pdfDataUri=await(pdfDoc.saveAsBase64({ dataUri: true }));
pdfDataUri;
`;
var pdfDataUri=loadWithGlobalPool({
name:"pdf-lib-nashorn",
max:10,
initializer:initscript,
script:runscript,
context:{bytesIPAexgothic:bytesIPAexgothic,createdate:new Date().format("mm:ss SSS")},
engine:"nashorn",
returnVar:"pdfDataUri",
});
return new Result().eval("$('"+params.pdf+"')[0].src='" +pdfDataUri +"'");
}
jsp is almost the same as last time, so I will omit the explanation.
pdfmake exam source
- global.js
var global={};
var ipaexg00401_ttf=null;
global.fire=function(){
ipaexg00401_ttf=encodeBytestoBase64forPdfMake(file.readAllBytes("font/ipaexg00401.ttf"));//IPAexゴシック
efw.register("ipaexg00401_ttf");
}
function encodeBytestoBase64forPdfMake(aBytes) {
//Byte配列をUint8Arrayに変換する
var temp = new Uint8Array(aBytes.length);
temp.set(Java.from(aBytes));
aBytes=temp;
//base64の文字列を作成する
var nMod3 = 2, sB64Enc = '';
for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
nMod3 = nIdx % 3;
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += '\r\n'; }
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
nUint24 = 0;
}
}
return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '==');
//------------
function uint6ToB64 (nUint6) {
return nUint6 < 26 ?
nUint6 + 65
: nUint6 < 52 ?
nUint6 + 71
: nUint6 < 62 ?
nUint6 - 4
: nUint6 === 62 ?
43
: nUint6 === 63 ?
47
:
65;
}
}
- testJavet.js
var testJavet={};
testJavet.paramsFormat={
pdf:null
};
testJavet.fire=function(params){
var initscript=`
const pdfMake = require(_eventfolder+"/pdfmake.min.js");
//require(_eventfolder+"/vfs_fonts.min.js");
pdfMake.vfs={};
pdfMake.vfs["ipaexg00401.ttf"]=ipaexg00401_ttf;
var fonts={
"IPAexゴシック":{
normal:"ipaexg00401.ttf",
bold:"ipaexg00401.ttf",
italics:"ipaexg00401.ttf",
bolditalics:"ipaexg00401.ttf",
},
}
`;
var runscript=`
var docDefinition = {
content: [
{ text:"hello world!こんにちは東京", fontSize: 20 },
],
defaultStyle: {
font:"IPAexゴシック"
}
};
var doc=pdfMake.createPdf(docDefinition,null,fonts);
var pdfDataUri;
(async function(){
pdfDataUri=await new Promise(function(resolve,reject){
doc.getDataUrl(function(data){
resolve(data);
});
});
})();
pdfDataUri="aaaa";
`;
var pdfDataUri=loadWithGlobalPool({
name:"pdfMake-javet",
max:10,
initializer:initscript,
script:runscript,
context:{ipaexg00401_ttf:ipaexg00401_ttf},
engine:"javet",
returnVar:"pdfDataUri",
});
return new Result().eval("$('"+params.pdf+"')[0].src='" +pdfDataUri +"'");
}
- testNashorn.js
var testNashorn={};
testNashorn.paramsFormat={
"pdf":null
};
testNashorn.fire=function(params){
var initscript=`
load(_eventfolder+"/pdfmake.min.js");
//load(_eventfolder+"/vfs_fonts.min.js");
pdfMake.vfs={};
pdfMake.vfs["ipaexg00401.ttf"]=ipaexg00401_ttf;
var fonts={
"IPAexゴシック":{
normal:"ipaexg00401.ttf",
bold:"ipaexg00401.ttf",
italics:"ipaexg00401.ttf",
bolditalics:"ipaexg00401.ttf",
},
}
`;
var runscript=`
var docDefinition = {
content: [
{ text:"hello world!こんにちは東京", fontSize: 20 },
],
defaultStyle: {
font:"IPAexゴシック"
}
};
var doc=pdfMake.createPdf(docDefinition,null,fonts);
var pdfDataUri=await(
new Promise(function(resolve,reject){
doc.getDataUrl(function(data){
resolve(data);
});
})
);
pdfDataUri;
`;
var pdfDataUri=loadWithGlobalPool({
name:"pdfMake-nashorn",
max:2,
initializer:initscript,
script:runscript,
context:{ipaexg00401_ttf:ipaexg00401_ttf},
engine:"nashorn",
returnVar:"pdfDataUri",
});
return new Result().eval("$('"+params.pdf+"')[0].src='" +pdfDataUri +"'");
}
Test results for 10 simultaneous PDF creations
pdf-lib
Nashorn first time is 33 seconds, next time is 5 seconds.
Javet 10 seconds the first time, 1 second the next time.
pdfmake
Nashorn first time 61 seconds, second time 19 seconds.
Javet 7 seconds the first time, 2 seconds the next time.
Conclusion
It's a true V8. It's very fast. If your Efw environment requires a large number of features from ES2015 or higher, loadWithGlobalPool + Javet may be a good choice.
Outlook
Is there a possibility to switch the Javascript engine of Efw main body to Javet?
Environment
JDK is 15 or higher, tomcat is 7, 8, or 9, and jar is below.
<dependency>
<groupId>io.github.efwgrp</groupId>
<artifactId>efw</artifactId>
<version>4.07.009</version>
</dependency>
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>15.4</version>
</dependency>
<dependency>
<groupId>com.caoccao.javet</groupId>
<artifactId>javet</artifactId>
<version>3.0.0</version>
</dependency>
sample source
These are the hello-pdf-lib3 and hello-pdfmake3 folders in the repository below.