Exposing dynamically created functions on objects with closure compiler - google-closure-compiler

I am trying to annotate my javascript so that closure doesnt rename all the symbols since i am working with vanilla javascript as well.
/**
* #constructor
* #expose
* #type{foo}
*/
foo = function (el, args) {
"use strict";
var s = "Hello World";
/*
* #expose
* #this {foo}
* #type {function}
*/
this.introduce = function () {
return s;
};
};
However the generated output when i run it through the closure compiler with advanced optimization is
foo = function() {
this.a = function() {
return"Hello World"
}
};
How do i ask closure to preserve the name introduce since this will be called from an external javascript.

The following options may be used to prevent the Closure Compiler from renaming
symbols:
#export (also see: goog.exportSymbol or goog.exportProperty)
Export symbols by storing them on the global object referenced by a string.
See Export the Symbols You Want to Keep
Define an interface in an externs file and implement the interface (see linked answers below)
Quote properties
Note: #expose has been deprecated
If you do not want to define methods on the function prototype as shown in your
example, then you could export the constructor foo with goog.exportSymbol
and use #expose to export methods.
/**
* #param {Element} el
* #param {...*} args
* #constructor
*/
var foo = function (el, args) {
"use strict";
/** #private */
this.msg_ = "Hello World";
/**
* #this {foo}
* #return {string}
* #expose
*/
this.introduce = function () {
return this.msg_;
};
};
goog.exportSymbol('foo', foo);
By defining methods on the function prototype, goog.exportSymbol can be
used to export both the constructor as well as method names.
/**
* #param {Element} el
* #param {...*} args
* #constructor
*/
var foo = function (el, args) {
"use strict";
/** #private */
this.msg_ = 'Hello World!';
};
goog.exportSymbol('foo', foo);
/**
* #return {string}
*/
foo.prototype.introduce = function () {
return this.msg_;
};
goog.exportSymbol('foo.prototype.introduce', foo.prototype.introduce);
See these related stackoverflow questions:
Why does Closure compiler rename properties of an extern type?
Can I tell the Closure compiler to, for specific types only,
stop renaming properties?
John's answer to the question: How to tell Closure Compiler to
preserve properties on an object

Related

Closure Compiler no longer able to determine type

I've been using Google's Closure Compiler for most of my projects, and a few of them in advanced mode with 100% typed.
One of my projects though no longer gets stated as 100% typed and I get warnings for things that I didn't used to get them for, and I can't seem to be able to figure out why. This is the message I get
WARNING - could not determine the type of this expression
v['children'].map(v => new _ChildLineItem(v['child'], v['option'], v['quantity'], v['price'])))))),
^
There's 42 more warnings like it, all about the same code, which I have here
/**
* #constructor
* #param {Array<!_Quote>} quotes
* #param {string} email
* #param {?string} quoteid
*/
function _GetQuotes(quotes, email, quoteid) {
this.quotes = quotes;
this.email = email;
this.quoteid = quoteid;
}
/**
* #constructor
* #param {string} quoteid
* #param {boolean} shipping
* #param {Array<!_Proof>} proofs
* #param {Array<!_LineItem>} lineitems
*/
function _Quote(quoteid, shipping, proofs, lineitems) {
this.quoteid = quoteid;
this.shipping = shipping;
this.proofs = proofs;
this.lineitems = lineitems;
}
/**
* #constructor
* #param {string} number
* #param {string} main
* #param {string} thumbnail
*/
function _Proof(number, main, thumbnail) {
this.number = number;
this.main = main;
this.thumbnail = thumbnail;
}
/**
* #constructor
* #param {string} name
* #param {number} quantity
* #param {number} price
* #param {Array<!_ChildLineItem>} children
* */
function _LineItem(name, quantity, price, children) {
this.name = name;
this.quantity = quantity;
this.price = price;
this.children = children;
}
/**
* #constructor
* #param {string} child
* #param {string} option
* #param {number} quantity
* #param {number} price
* */
function _ChildLineItem(child, option, quantity, price) {
this.child = child;
this.option = option;
this.quantity = quantity;
this.price = price;
}
Ajax({
url: '/ajax/getquotes',
data: Data,
success: function (/** !_GetQuotes */ data) {
var d = new _GetQuotes(
data['quotes'].map(v => new _Quote(v['quoteid'], v['shipping'],
v['proofs'].map(v => new _Proof(v['number'], v['main'], v['thumbnail'])),
v['lineitems'].map(v => new _LineItem(v['name'], v['quantity'], v['price'],
v['children'].map(v => new _ChildLineItem(v['child'], v['option'], v['quantity'], v['price'])))))),
data['email'], data['quoteid']);
...
I can rewrite the closures to specify the types of the objects coming through like this
v['children'].map(function( /** !_ChildLineItem */ v) { new _ChildLineItem(v['child'], v['option'], v['quantity'], v['price'])}
But shouldn't it be able to figure that out from the constructor definitions?
Actually me specifying all of them like this isn't even working
var d = new _GetQuotes(
data['quotes'].map((/** !_Quote */ v) => new _Quote(v['quoteid'], v['shipping'],
v['proofs'].map((/** !_Proof */ v) => new _Proof(v['number'], v['main'], v['thumbnail'])),
v['lineitems'].map((/** !_LineItem */ v) => new _LineItem(v['name'], v['quantity'], v['price'],
v['children'].map((/** !_ChildLineItem */ v) => new _ChildLineItem(v['child'], v['option'], v['quantity'], v['price'])))))),
data['email'], data['quoteid']);
With this warning
WARNING - could not determine the type of this expression
v['children'].map((/** !_ChildLineItem */ v) => new _ChildLineItem(v['child'], v['option'], v['quantity'], v['price'])))))),
^^^^^^^^^^^^^^^^^
The problem you are facing is that the compiler generally treats computed and dot property accesses differently. Computed property accesses are treated as the 'unknown' type unless you give a type signature the [] operator (i.e. the class implements IArrayLike as Array does or IObject[2] for map like objects).
Although, the compiler could understand that x.foo and x['foo'] are reference the same property, it does not currently do this.
[1] https://github.com/google/closure-compiler/wiki/Special-types-in-the-Closure-Type-System

Synfony3 Console: Add own helper to HelperSet

Is there a way to add own helpers to the console HelperSet in Symfony3?
I didn't find any helpful thing in the documentation.
Ok i followed the code and find a simple solution. :)
I just have to add my class that implements the HelperInterface, or extend the abstract Helper class.
$this->getHelperSet()->set(new MyHelper(), 'myhelper');
And myhelper class looks like that:
<?php
namespace MyApp\Helper;
use Symfony\Component\Console\Helper\Helper;
class MyHelper extends Helper
{
/**
* #param $string
* #return string
*/
public function doIt($string) {
return 'this is your '.$string;
}
/**
* Returns the canonical name of this helper.
*
* #return string The canonical name
*/
public function getName() {
return 'myhelper';
}
}
And in my code i can use it like:
$myhelper = $this->helperSet->get('myhelper');
$myString = $myhelper->doIt('hallo');
:)

phpunit test depending on other test that uses dataprovider

I've this situation
public class MyTest extends .... {
function providerA(){
return array(array("a"));
}
function providerB(){
return array(array("b"));
}
/**
* #dataProvider providerA
*/
function testOne($a){
$c = "something";
return $c;
}
/**
* #depends testOne
* #dataProvider providerB
*/
function testTwo($b,$c){
var_dump($b);
var_dump($c);
}
}
var_dump($c) -> is always null, why?
I cannot figure out what is happened. On the pdf of phpunit I found this sentence:
"When a test depends on a test that uses data providers, the depending test will be executed
when the test it depends upon is successful for at least one data set. The result of a test that
uses data providers cannot be injected into a depending test."
How can achieve my goal or a result that work in the same way?
I'd suggest to make a static property, which will be filled with data from the testOne. Because of the #depends annotation, testTwo will not run if testOne fails. testOne will add value to the static property c which will be used in the testTwo test.
However, I think better practice is to separate both tests. Thus, the data needed for testTwo will all provided by providerB (not depended on other test).
private static $c = array(array("c"));
function providerA() {
return array(array("a"));
}
/**
* #dataProvider providerA
*/
function testOne($a) {
$c = "something";
self::$c[0][] = $c;
$this->assertTrue(true);
}
/**
* #depends testOne
*/
function testTwo() {
var_dump(self::$c);
}

Closure Compiler Externs - WARNING - Property never defined on

I am preparing externs for PIXI.js library. I am getting the following warning:
js/Test.js:188: WARNING - Property position never defined on PIXI.Sprite
button.position.y = y;
Here are the relevant extern definitions:
//UPDATE
/**
* #constructor
* #extends {PIXI.Container}
* #param {PIXI.Texture} texture
*/
PIXI.Sprite = function(texture){};
/**
* #constructor
* #extends {PIXI.DisplayObject}
*/
PIXI.Container = function(){};
/**
* #constructor
* #extends {PIXI.EventEmitter}
*/
PIXI.DisplayObject = function(){};
/**
* #type {PIXI.Point}
*/
PIXI.DisplayObject.position;
Still getting the same warning.
What am I doing wrong?
When I am replacing PIXI.DisplayObject.position; with PIXI.DisplayObject.prototype.position; that seems to clear the warning.
Does it mean that I should always define SomeObject.prototype.prop rather then SomeObject.prop ?
This is highlighting the difference between static and prototype properties.
Given:
/**
* #constructor
* #param {number=} opt_num
*/
function foo(opt_num) {
if (opt_num !== undefined) {
this.bar = opt_num;
}
}
foo.prototype.bar = 17;
foo.bar = 42;
We have both a static property and a prototype property of the same name. However they are referenced differently:
console.log((new foo()).bar); // 17
console.log((new foo(0)).bar); // 0
console.log(foo.bar); // 42
So in an extern, when you are defining properties on a type - you typically want to define them on the prototype object:
/** #param {foo} obj_foo */
function log(obj_foo) {
// This is an instance of "foo".
// The "bar" property references prototype or instance
// properties - not static properties.
console.log(obj_foo.bar);
// Static properties can only be referenced by the full namespace
console.log(foo.bar);
}

optional parameters in routes defined through annotations

is there a more elegant way to define optional parameters in annotated routes then to define 2 annotations?
Here's how I did it:
/**
*
* #Route("/view/{lang}/{file}", name="legacy_translation_view_file")
* #Route("/view/{lang}", name="legacy_translation_view")
* #Template()
*/
public function viewAction($lang,$file=null)
{
...
}
i've seen that the annotation class has a field named "defaults" but am not quiet sure about the syntax
thx
Symfony has a page on #Route:
E.g maybe you can try.
/**
* #Route("/{id}/{lang}/{file}", requirements={"id" = "\d+"}, defaults={"file" = null})
*/
public function showAction($id, $lang, $file)
{
}
If null doesn't work try an empty string.

Resources