Functioning code no longer working after being minified and deployed - javascript

I have some code in a web worker that is working perfectly locally, but as soon as I build and deploy (which minifies the code) it no longer works.
The unminified code looks like this:
const mapSourceCode = (treeNode, mfi, {objectType, types, fileType, templateType}) => {
let sourceCodeMap = new Map();
let ownerMap = new Map();
let sourceCodeList = [];
let ownerList = [];
let mfiMap = new Map();
mfi.forEach(row => mfiMap.set(row.uuid, row));
let sourceCodeObjects = mfi.filter(row => types.includes(row.objectTypeUuid));
if(sourceCodeObjects.length < 1)
return {sourceCodeMap, sourceCodeTree: undefined};
try {
sourceCodeObjects.forEach(sourceObj => {
let owner = findOwner(sourceObj, sourceObj, mfiMap, {...treeNode.data}, objectType);
The minified code is this:
i = function(e, t, n) {
var c = n.objectType
, o = n.types
, i = n.fileType
, u = n.templateType
, l = new Map
, s = new Map
, f = []
, p = []
, m = new Map;
t.forEach((function(e) {
return m.set(e.uuid, e)
}
));
var h = t.filter((function(e) {
return o.includes(e.objectTypeUuid)
}
));
if (h.length < 1)
return {
sourceCodeMap: l,
sourceCodeTree: void 0
};
try {
if (h.forEach((function(n) {
var r = a(n, n, m, Object(d.a)({}, e.data), c);
The line it's erroring out on is {...treeNode.data} on the last line.
The error is ReferenceError: d is not defined
I can't figure out what the issue could be? Like I said everything runs great on locally. Any help is greatly appreciated

I found the issue, in case anybody runs into this same thing.
Normally when using web workers you need to tell your builder (webpack) to build / compile workers separately. I'm using the default create-react-app configuration which doesn't give access to that part of webpack. unless you eject from create-react-app completely (which I'm currently not ready to do)
I'm using the react hook called useWorker, where I pass the function I want to allocate to the worker.
When your code is optimized and minified variable names are replaced with smaller names (mostly 1 or 2 letters from what I've seen). Because I didn't have any custom loaders to load my worker code, it used variables from the global scope assuming it would have access. When the code was extracted to a separate thread outside the main thread it no longer had access to those variables and thus didn't work.
The fix is to
Add a loader (you can either eject from create-react-app, or there may be some npm libraries that will give you access to that particular part of webpack)
Or my solution was to create the function in a string and create a function using the Function constructor like so
const generateFunction = new Function('treeNode', 'mfi', 'types', 'action', generateFunctionString);
Where the generateFunctionString was a string like: "return a + b"
I then passed that function into my useWorker hook:
const [generatorWorker] = useWorker(generateFunction);

Related

Netlify Serverless Function returning 404

I am trying to set up a simple serverless function on Netlify just to test out usage of environment variables. I have defined the following two environment variables in Netlify for my site:
Variable Name
Value
ALPHABET_SEPARATION
2
CHARS_BETWEEN
3
I have also updated my functions directory as follows:
Functions directory: myfunctions
I am using continuous deployment from github. As I do not know the use of npm at present and finding it convenient to directly test the production deploy, I have defined a subdirectory called myfunctions inside my root directory and have placed my javascript file containing the "serverless" function inside it on my local machine. I have built in logic so that the "serverless" function gets called only when a "netlify" flag is set, otherwise, an alternate function gets executed client-side. Basically it works as follows:
const deploy = "netlify" //Possible valid values are "local" and "netlify"
async function postRandomString() {
const stringToUpdate = "THISISATESTSTRING"
var stringToPost = "DUMMYINITIALVALUE";
if (deploy === "local") {
stringToPost = updateString(stringToUpdate); //updateString is a function defined elsewhere and executes client-side;
}
else if (deploy === "netlify") {
const config = {
method: 'GET',
headers: {
'Accept': 'application/json',
}
};
const res = await fetch(`myfunctions/serverUpdateString?input=${stringToUpdate}`, config);
const data = await res.json();
stringToPost = data.retVal;
console.log(data.retVal);
}
else {
stringToPost = "##ERROR##";
}
postString(stringToPost); //postString is a function defined elsewhere and executes client-side;
}
The serverless function file serverUpdateString.js is coded as follows (it basically sets a character at a certain position (determined by CHARS_BETWEEN) in the string to an alphabetical character which is a certain number (determined by ALPHABET_SEPARATION) of places in the alphabet after the first character of the string (don't ask why - the point is that it never even receives/handles the request):
exports.handler = async function (event) {
const { CHARS_BETWEEN, ALPHABET_SEPARATION } = process.env;
const charsBetween = CHARS_BETWEEN;
const alphabetSeparation = ALPHABET_SEPARATION;
const initString = event.queryStringParameters.input;
const rootUnicode = initString.charCodeAt(0);
const finalUnicode = "A".charCodeAt(0) + (rootUnicode - "A".charCodeAt(0) + alphabetSeparation) % 26;
const finalChar = String.fromCharCode(finalUnicode);
const stringArray = initString.split("");
stringArray[charsBetween + 1] = finalChar;
const stringToReturn = stringArray.join("");
const response = {
statusCode: 200,
retVal: stringToReturn,
}
return JSON.stringify(response);
}
When I run it, I get a 404 error for the GET request:
In the above image, script.js:43 is the line const res = await fetch(myfunctions/serverUpdateString?input=ATESTSTRIN, config); in the calling file, as shown in the first code block above.
What am I doing incorrectly? Surely Netlify should be able to pick up the serverless function file given that I have specified the folder alright and have placed it at the right place in the directory structure? I have given the whole code for completeness but the problem seems quite elementary. Look forward to your help, thanks.
I got assistance from Netlify forums. Basically the following changes needed to be made:
The fetch request -- line 43 in the calling code (script.js) -- needed to be changed to
const res = await fetch(`https://netlifytestserverless.netlify.app/.netlify/functions/serverUpdateString?input=${stringToUpdate}`, config);
The return statement in the lambda function needed to be changed to:
const response = {
statusCode: 200,
body: JSON.stringify(stringToReturn),
}
Other minor changes such as using parseInt with the environment variables.
The code works now.

Build JS from SJSIR `manually`

I need to build a js file from sjsir files at runtime to implement a system of plugins, so that it can't be done at compile time with the rest of my compilation. I used to implement the same process in 0.6.3 with the following code, but it seems to be deprecated. What algorithm do you recommand to achieve the same action with 0.6.13 ?
Thanks
val scalajsLib = copyJar("scalajs-library_2.11-0.6.3")
val semantics = org.scalajs.core.tools.sem.Semantics.Defaults
val partialClasspath =
PartialClasspathBuilder.build(collection.immutable.Seq(scalajsLib, src))
val completeClasspath = partialClasspath.resolve()
val optimizer = new ScalaJSOptimizer(semantics)
val logger = new ScalaConsoleLogger
val out = WritableFileVirtualJSFile(
new java.io.File(target, JS_FILE))
if (optimized) {
val sems = semantics.optimized
new ScalaJSClosureOptimizer(sems).optimizeCP(
new ScalaJSOptimizer(sems),
completeClasspath,
ScalaJSClosureOptimizer.Config(out),
logger
)
} else {
optimizer.optimizeCP(
completeClasspath,
ScalaJSOptimizer.Config(out, checkIR = false, wantSourceMap = !optimized),
logger
)
}
The Tools API has dramatically changed in 0.6.5, indeed. It became much simpler and more able to evolve in non-breaking ways in the future.
Your code above can be written with the new API as follows:
import java.io.File
import org.scalajs.core.tools.io._
import org.scalajs.core.tools.sem._
import org.scalajs.core.tools.linker.backend.{OutputMode, ModuleKind}
import org.scalajs.core.tools.linker.Linker
import org.scalajs.core.tools.logging.ScalaConsoleLogger
def link(inputClasspath: Seq[File], outputJSFile: File): Unit = {
// Obtain VirtualScalaJSIRFile's from the input classpath
val irCache = new IRFileCache().newCache
val irContainers = IRFileCache.IRContainer.fromClasspath(inputClasspath)
val sjsirFiles = irCache.cached(irContainers)
// A bunch of options. Here we use all the defaults
val semantics = Semantics.Defaults
val outputMode = OutputMode.Default
val moduleKind = ModuleKind.NoModule
val linkerConfig = Linker.Config()
// Actual linking
val linker = Linker(semantics, outputMode, moduleKind, linkerConfig)
val logger = new ScalaConsoleLogger
linker.link(sjsirFiles, WritableFileVirtualJSFile(outputJSFile), logger)
}
And you can call that link function with the following arguments, to exactly match your above snippet:
link(Seq(scalajsLib, src), new java.io.File(target, JS_FILE))
If you intend to call this method several times on the same classpath within the same process, it is advised to cache and reuse the instances irCache and linker across runs, as this will considerably speed up the process.
See also the Scaladoc of the Tools API.
Is there a way to prevent from errors about class repetition in the batch of sjsir (which generates the message: XXX already seen) at link time ? I guess it is, since this error does not occur when the build is done at compile time from the build.sbt.

flatbuffers is not defined

I'm writing a nodeJs application that uses google flat buffer.
I installed flatc on my macbook pro and compiled the following schema:
namespace MyAlcoholist;
table Drink {
drink_type_name: string;
drink_company_name: string;
drink_brand_name: string;
drink_flavor_type_name : string;
liquid_color_type_name : string;
liquid_color_is_transparent : bool;
alcohol_vol : float;
calories_for_100g : uint;
global_image_id: ulong;
drink_flavor_id: ulong;
}
table Drinks { drinks:[Drink]; }
root_type Drinks;
the schema file is called drink.fbs and it generated a javascript file called drink_generated.js
I include this file in my nodejs application and add data to it using the following code.. this is my flatBufferUtil.js utility file.
var flatbuffers = require('../js/flatbuffers').flatbuffers;
var builder = new flatbuffers.Builder();
var drinks = require('../fbs/drinks_generated').MyAlcoholist; // Generated by `flatc`.
function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
var drinkObj = element;
var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
var drinkTypeName = builder.createString(drinkObj.drink_type_name);
var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
drinks.Drink.startDrink(builder);
drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
drinks.Drink.addCaloriesFor100g(builder,drinkObj.calories_for_100g);
drinks.Drink.addDrinkBrandName(builder,drinkBrandName);
drinks.Drink.addDrinkCompanyName(builder,drinkCompanyName);
drinks.Drink.addDrinkFlavorId(builder,drinkObj.drink_flavor_id);
drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
drinks.Drink.addDrinkTypeName(builder,drinkTypeName);
drinks.Drink.addGlobalImageId(builder,drinkObj.global_image_id);
drinks.Drink.addLiquidColorIsTransparent(builder,drinkObj.is_transparent);
drinks.Drink.addLiquidColorTypeName(builder,liquidColorTypeName);
var drink = drinks.Drink.endDrink(builder);
drinksVectArray.push(drink);
})
var drinksVect = drinks.createDrinksVector(builder,drinksVectArray);
builder.finish(drinksVect);
var buf = builder.dataBuffer();
return buf;
}
module.exports.drinkArrayToBuffer=drinkArrayToBuffer;
now when I execute this function it fails with the error flatbuffers is not defined.
I debugged my code and I saw that it files on the following line of code:
drinks.Drink.addDrinkFlavorId(builder,drinkObj.drink_flavor_id);
if i get inside addDrinkFlavorId function i see this code in drinks_generted.js:
MyAlcoholist.Drink.addDrinkFlavorId = function(builder, drinkFlavorId) {
builder.addFieldInt64(9, drinkFlavorId, flatbuffers.Long.ZERO);
};
as you can see it uses flatbuffers.Long.ZERO but flatbuffers is not defined in that file at all. the compilation did not provide any errors so what do I miss?
It seems to me like it is a bug... The generated file appears to be meant to exist autonomously from the flatbuffers require. However for the custom flatbuffers.Long class, the default of flatbuffers.Long.ZERO bleeds into the generated file.
While this isn't a solution per-say, one workaround is to manually add the flatbuffers require to the generated file; it's ugly, but it might be better than being blocked until a more appropriate answer (or fix) comes around.
// In `drinks_generated.js`
var flatbuffers = require('../js/flatbuffers').flatbuffers;
Note:
The drinks.Drink.addDrinkFlavorId() and drinks.Drink.addGlobalImageId() functions expect flatbuffers.Long values to be passed into them, because they were specified as ulong in the schema (fbs file). So you will need to ensure that you are not trying to pass in a simple number type.
For example:
var my_long = flatbuffers.Long(100, 0); // low = 100, high = 0
drinks.Drink.addDrinkFlavorId(builder, my_long);
As a result, another possible workaround is to change the datatype of those fields in the schema to avoid using ulong until it becomes more clear what is going on here.
P.S. I am pretty sure drinks.createDrinksVector on line 30 of that snippet should be drinks.Drinks.createDrinksVector.

XML parsing syntax for OS X Yosemite JavaScript for Automation?

Has anyone deduced syntax which successfully loads XML from file/string and gives access to the data in OS X Yosemite (10.10) Javascript for Automation ?
Documentation and code samples are still fairly thin (as of Nov 2014), and my inductive skills are running dry on three separate approaches to reading an XML (OPML) file at the moment:
Most promising: $.NSXMLDocument
Getting hold of the string data in various ways goes well,
function readTextFromFile(strPath) {
return $.NSString.stringWithContentsOfFile(strPath);
}
function readDataFromFile(strPath) {
return $.NSData.alloc.initWithContentsOfFile(strPath);
}
function filePath(strPath) { return Path(strPath); }
But no permutations on this theme have borne fruit:
var strPath='/Users/houthakker/Desktop/notes-2014-11-04.opml',
dataXML = readData(strPath),
strXML = readTextFile(strPath),
oXMLDoc1, oXMLDoc2;
oXMLDoc1 = $.NSXMLDocument.alloc.initWithXMLString(strXML,0,null);
oXMLDoc2 = $.NSXMLDocument.alloc.initWithData(dataXML,0,null);
(the 'function undefined' error messages suggest that those two init functions may not be exposed, though initWithRootElement() does seem to be)
Most progress: $.NSXMLParser
var oParser = $.NSXMLParser.alloc.initWithData(dataXML);
return oParser.parse; //true
But event-driven parsing seems to require some further complexities which remain opaque to me, and which may not match my simple needs (reading and converting modestly sized local OPML files).
Most familiar: Application("System Events")
In Applescript this can be done with System Events code:
set fOPML to (POSIX file "/Users/houthakker/Desktop/notes-2014-11-04.opml" as alias) as string
tell application "System Events"
tell XML file fOPML
-- now access XML Elements by name or index
end tell
but I haven't found a successful javascript idiom for initializing the XMLFile object with any permutation of a unix Path(), string, or colon-delimited mac path string.
Any thoughts or more successful experience here ?
This turns out to work for the (very slow executing) Application("System Events") route:
var app = Application("System Events"),
strPath = '~/Desktop/summarise.opml';
var oFile = app.xmlFiles[strPath],
oRoot = oFile.xmlElements[0],
oHead = oRoot.xmlElements.head,
oBody = oRoot.xmlElements.body,
lstOutlineXML = oBody.xmlElements.whose({
name: 'outline'
});
And the function for initialising an NSXMLDocument from an XML string is, according to the JSExport convention (in which the letter following each ":" is capitalized, and then the ":"s are removed) .initWithXMLStringOptionsError()
Thus, to choose a local OPML file and parse it to a simple JSON outline:
function run() {
var app = Application.currentApplication();
app.includeStandardAdditions = true;
function readTextFromFile(strPath) {
return $.NSString.stringWithContentsOfFile(strPath);
}
var strPath = (
app.chooseFile({withPrompt: "Choose OPML file:"})
).toString(), // Path → String
strXML = strPath ? readTextFromFile(strPath) : '';
if (!strXML) return;
var oXMLDoc1 = $.NSXMLDocument.alloc.initWithXMLStringOptionsError(strXML, 0, null),
oRoot = oXMLDoc1.rootElement,
oBody = ObjC.unwrap(oRoot.children)[1],
lstOutline = ObjC.unwrap(oBody.children),
lstParse, strJSON;
function parseOPML(lst) {
var lstParse=[], oNode, dctNode, lstChiln;
for (var i = 0, lng=lst.length; i<lng; i++) {
oNode = lst[i];
dctNode = {};
dctNode.txt = ObjC.unwrap(oNode.attributeForName('text').stringValue);
lstChiln = ObjC.unwrap(oNode.children);
if (lstChiln && lstChiln.length)
dctNode.chiln = parseOPML(lstChiln);
lstParse.push(dctNode);
}
return lstParse;
}
lstParse = parseOPML(lstOutline);
strJSON = JSON.stringify(lstParse,null, 2);
app.setTheClipboardTo(strJSON);
return strJSON;
}

this._get is not a function - javascript oop and prototypes

I'm using something similar to NodeJS called bondi, it's build on the Firefox js engine.. Basically i'm getting this error and I believe it's due to the way i'm referencing "this" in the .Get function below.
Basically there is a tool called SFtpClient. It has the method of "Get", to list the contents of a folder, but I want to change the prototype for this with a drop in include file. I need to change it so that it
a/ retries several times when it fails, and b/ it has a recursive folder listing function.
So I used the prototype to change it - moved .Get to ._Get.
Can anyone see why I would be getting the error:
Jan 23 04:51:34 beta bondi: === this._Get is not a function --- Prio(6) Result(0x0) File(/home/nwo/approot/include/sftpclientenh
when I run the code below?
Thanks
SFtpClient.prototype._Get = SFtpClient.prototype.Get;
SFtpClient.prototype.Get = function(Folder, Retries){
//defaults
if(!Retries) Retries = 5;
if(!Folder) Folder = "~/";
//vars
var FileListing = [];
var connect = function(){
//TODO JRF 19.01.2012 : re-enable this when bondi is fixed
// this.HomeDirectory.replace(/\/?$/, "/");
FileListing = this._Get(Folder);
return true;
}
var i = 1;
do{
var res = false;
try {
res = connect();
}catch(e){
Debug.LogInfo(e.message);
}
i++;
Server.Sleep(i*2000);
} while(res==false && i < Retries);
return FileListing;
}
Try res = connect.call(this) instead of res = connect().

Categories

Resources