I work on a project which uses Google's closure compiler with advanced optimizations turned on. I would like to include moment.js in the compilation, however all of my attempts have been fruitless.
I have tried exporting the moment function, but there are still run time problems, and a some compile errors.
Has anyone successfully compiled moment.js with advanced optimizations, or know how to do so?
The only solution I can come up with, is to concatenate the minified file to the compiled source and use externs for every function I use from moment.js. But this is not an ideal solution.
I saw two issues with the code which would have to be corrected before momentjs would be compatible with ADVANCED_OPTIMIZATIONS. There may be more, but these were the glaring ones:
Using an alias for the prototype: All references to .fn would need to be replaced with .prototype.
Using a helper function to add methods: the extend method hides definitions from the compiler. All uses of the extend helper function would have to be refactored so that they do not hide the property assignments from the compiler.
I can't get it to work either as of 26 March 2015, but the existence of this suggests that it's possible. Here are the externs
You've gotta write your own externs file for moment.js for what you use from it (or the entire object, but I find that a bit of extra work for no reason).
For example, I've got this snippet to test if an input's date is within 14 days from now
$checkout.find('.date-input').on('input', /** #this {Element} */ function () {
const $this = $(this);
const Days = Number($this.attr('data-days'));
if (Days > 0 && moment(/** #type {string} */($this.val())).diff(moment(), 'days') < Days) {
$checkout.find('.date-warning').removeClass('d-none');
} else {
$checkout.find('.date-warning').addClass('d-none');
}
});
And the only way I'd get that to compile correctly with advanced mode is by creating this extern.
/**
* #fileoverview Externs for moment
*
* #externs
*/
/**
* #param {string=} date
* #constructor
* #return {!moment}
*/
function moment(date) {}
/**
* #param {!moment} m
* #param {string} unit
* #return {number}
*/
moment.diff = function (m, unit) {};
moment.prototype.diff = moment.diff;
Now clearly that description of the moment function isn't perfect; it's missing some parameters that the moment function has, but I'm not using them so it doesn't matter to me.
But that's how I start my externs. I start basic as the need arises and then I continue to grow the externs file with the more functions I need from a library.
And don't forget to tell Closure Compiler where your extern is located with the flag --externs 'externs/moment.js'.
Related
What I mean specifically is if it's possible to have some code written, say in C (or some other compiled language), and then expose it and use from within a GJS runtime.
In fact, this is how all of GJS works. Just as node.js is ECMAScript on top of node's own platform, GJS was created so that ECMAScript could be used with the GNOME platform libraries.
This is effectively limited to C libraries written with GObject, but of course anything you can use from C can be wrapped into a GObject-based library. There are Boxed Types for integrating foreign structures into the GLib type system, or you can wrap things into the structure of a GObject subclass.
The principle is pretty straight-forward and relies on use GObject-Introspection Annotiations to express function signatures, memory ownership and so on. Below is a simple example:
/**
* namespace_copy_string:
* #input: (transfer none): an input string
*
* This function copies a string and returns the result.
*
* Returns: (transfer full): a new string
*/
char *
namespace_copy_string (const char *input)
{
return g_strdup (input);
}
The headers and source are then scanned for public symbols with these annotations, and use to generate an XML-format and compiled typelib. meson is the recommended build-system for GObject-based libraries and includes helpers for generating the introspection data. You can also use gi-docgen to easily generate documentation from this output.
Once installed, the result can be imported into any language binding that supports GObject-Introspection (GJS, Python, etc):
const Namespace = imports.gi.Namespace;
let copy = Namespace.copy_string("content");
I am trying to compile my code generated by browserify with Google Closure Compiler using Advanced Optimization.
Tried running browserify with different flags, no success so far.
Have any one have some experience with that?
I had to change the file: /node_modules/browserify/node_modules/browser-pack/_prelude.js with google closure annotations and add the externs files as
/**
* #param {*=}o
* #param {*=}u
*/
function require(o,u){}
What errors/warnings do you get?
I am having issue in assigning the return type of below method to a variable of integer type in advanced compilation mode of google closure. Also i don't want to use getter/setter method as a replacement for below code.
/**
* Sets the idNum of this shape.
* #override
* #param {...number} id The number to set idNum, optional parameter.
* #returns {number} Returns idNum if nothing is passed in.
*/
app.Shape.prototype.idNum = function(id) {
if(goog.isDef(id)) {
this._idNum = id;
} else {
return this._idNum;
}
};
How should i update my annotation for
#returns
so that above method may or may not return number depending on the parameter passed.
It's a little strange to have the same function be both a getter and a setter, depending on how it's called. But anyway: Use an = for the optional parameter: {number=}. For your "optional return" you can write the return type as {number|undefined} because if you don't hit a 'return' statement, the function will just return undefined. See Annotating JavaScript for the Closure Compiler for more.
The Closure Compiler doesn't support having more than one signature for a function, you basically want:
/** #type {(function(number):undefined)|(function():number)} */
Currently, the compiler merges this into "Function". More specifically, you want to say not that it is either of those types but both of those types and there is nothing like that now.
While you can manually merge the function signature to be:
/**
* #param {number=} opt_id
* #return {number|undefined}
*/
This means the return type is always "number|undefined" not the return type is "undefined" when the parameter is specified and "number" otherwise when leaves consumers having to "narrow" the results to either "number" or "undefined" after every call which is an awkward api.
While having a function be both a getter and a setter is not strange in many scenarios, you are fighting against what Closure Compiler is trying to do for you.
JavaScript is loosely-typed, meaning anything can be "this type OR that type OR another type OR ...." with no limit on the size of this list.
CC is trying to help by enforcing strong-types. The strongest possible typing insists that a given variable is "this one type only", but this rigidity is often a pain (not allowing a NULL or UNDEFINED value in particular). CC relaxes this by allowing "a few types only" that you must spell out. However, you should be aware that this relaxation is one small step backwards, towards the wild west of loose-typing.
If you are using CC to improve your code, then listen to what it is trying to tell you. If you find yourself fighting to find the right annotation for something, or your lists of types are growing, then maybe you need to reconsider your use of CC and strong-typing in the first place.
Personally, I prefer strong-typing and simpler, shorter, clearer code. In your example, CC is trying to help by obliquely hinting at the down-side of combining getter and setter functionality.
In the SUPPLY automatically-generated function modules, there can be seen the following comments:
* General Notes
* =============
* A common scenario for a supply method is to aquire key
* informations from the parameter <parent_element> and then
* to invoke a data provider.
* A free navigation thru the context, especially to nodes on
* the same or deeper hierachical level is strongly discouraged,
* because such a strategy may easily lead to unresolvable
* situations!!
*
** data declaration
* DATA lt_nod TYPE wd_this->Elements_nod.
* DATA ls_nod LIKE LINE OF lt_nod.
** #TODO compute values
** e.g. call a data providing **FuBa**
I understand the dangers of navigating through nodes that have an associated Supply Function but haven't been initialized yet - this basically leads to dead locks.
What i'd like to know is what's a FuBa, or data provider and how to use that - all the examples i've found only supply data for a node in a trivial manner, and don't tackle this problem.
Is that some way to register the nodes to be updated later... or... dunno ?
In this case, data provider is not a technical term, it's just some coding that provides the data you want to add to the context. Whatever that may be depends on your application context - anything from a local or remote function module or method call, a call to your assistance class or even - if you really want to adopt bad coding habits - to a direct database access.
FuBa is an abbreviation of Funktionsbaustein = function module.
I'm new to QDoc and I'm trying to figure out if I prefer it over Doxygen. There's one thing that annoys be.
QDoc will only look through *.cpp files for /*!-style comments, so I can't document inline functions and pure virtual functions.
Is there a workaround for this?
You can use the \fn command to refer to a function. For your two cases, put something like this in a .cpp file:
/*!
* \fn void AbstractClass::pureVirtualMethod()
*
* Some info here...
*/
/*!
* \fn void inlineFunction()
*
* Some info here...
*/