How to make Flow understand code written for Node.js? - flowtype

I'm just getting started with Flow, trying to introduce it into an existing Node codebase.
Here are two lines Flow complains about:
import Module from 'module';
const nodeVersion = Number(process.versions.node.split('.')[0]);
The warnings about these lines are, respectively:
module. Required module not found
call of method `split`. Method cannot be called on possibly null value
So it seems like Flow isn't aware of some things that are standard in a Node environment (e.g. process.versions.node is guaranteed to be a string, and there is definitely a Node builtin called module).
But then again, Flow's configuration docs suggest it's Node-aware by default. And I have plenty of other stuff like import fs from 'fs'; which does not cause any warning. So what am I doing wrong?

Module fs works as expected because Flow comes with built-in definitions for it, see declare module "fs" here: https://github.com/facebook/flow/blob/master/lib/node.js#L624
Regarding process.versions.node, you can see in the same file that the versions key is typed as a map of nullable strings, with no mention of the specific node property: versions : { [key: string] : ?string };. So you'll need to either make a PR to improve this definition, or adjust your code for the possibility of that value being null.
I guess the answer about module "module" is obvious now – there are no built-in definitions for that module in Flow in lib/node.js. You could write your own definitions, and optionally send a PR with them to the Flow team. You can also try searching github for these, someone might have done the work already.
That lib directory is very useful by the way, it has Flow definitions for DOM and other stuff as well.

Related

typescript, ts-morph module, is there access to underlying `ts.SourceFile` instance from a `ts-morph.SourceFile` instance?

I am trying out the ts-morph npm module to replace some code which I have already written but which overlaps ts-morph and is inferior. Nevertheless, I have some existing functions that take an ts.Node type arguments, mostly for exploration and discovery, which I need to use for reference while trying out ts-morph.
However, I can't see a way to access the underlying ts.Node instance from a ts-morph.SourceFile instance - there are no ts-morph functions with return type of ts.Node or ts.TypeChecker.
This doesn't work
(sourceFile as unknown) as ts.SourceFile,
(checker as unknown) as ts.TypeChecker,
because, for starters, (sourceFile as unknown) as ts.SourceFile doesn't have a kind member.
Is there a way access the underlying ts.Node instance from, e.g., ts-morph.SourceFile?
ts-morph provides access to all the underlying compiler API objects it wraps.
For any node, you can access the underlying compiler node using the compilerNode property:
sourceFile.compilerNode // ts.SourceFile
Note though that the underlying compiler node will become out of date whenever the source file is manipulated via ts-morph (ex. you add a class to the source file, remove a function, or other stuff like that).
https://github.com/dsherret/ts-morph/blob/af35677f3b498ed0f8e87e4b6c92a7246cfab210/packages/ts-morph/lib/ts-morph.d.ts#L3189
To get the TypeScript TypeChecker, use the compilerObject property on TypeChecker:
project.getTypeChecker().compilerObject // ts.TypeChecker

How do I tell Flow that there will be a class on window without explicitly specifying its type?

I want to incorporate the Google Maps JS library into a Flow-typed project. Since there aren't any remotely complete Flow externs for the library, I'd like to tell Flow to accept whatever methods and constants I call from the class as Function and any, respectively. I know that the best answer would be to write a complete extern for GMaps and post it on Github, but I've got deadlines to meet. Using flow-typed is also an option to generate stubs, but that only seems to work on npm packages. What would be the best way to tackle this?
If you want to completely skip checks, you can simply declare:
declare var google: any;
Which will allow you to do whatever you want to google:
google.maps.Map();
google();
google.maps.Map.call();
Or if you wanted to at least ensure you always call google.maps.something and never google by itself:
declare var google: { maps: Object };

Where did LoaderService go?

Upgrading AngleSharp from 0.9.6 to 0.9.9 I have this line of code no longer compiling:
return configuration.With(LoaderService(new[] { requester }));
It complains that LoaderService does not exist in the current context. So what happened to LoaderService? Is there a replacement? Does it still exist but just somewhere else?
Good question. Sorry for being late to the party, but even though you may have solved your problem someone else is having a hard time figuring it out.
LoaderService was essentially just a helper to create a loader. But having a service for anything creating a little thing would be overkill and not scale much. Also AngleSharp.Core would need to define all these. So, instead a generic mechanism was introduced, which allows registering such "creator services" via Func<IBrowsingContext, TService>.
However, to solve your piece of code I guess the following line would do the trick:
return configuration.WithDefaultLoader(requesters: requester);
This registers the default loader creator services (one for documents, one for resources inside documents) with the default options (options involve some middleware etc.).
Under the hood (besides some other things) the following is happening:
// just one example, config.Filter is created based on the passed in options
return configuration.With<IDocumentLoader>(ctx => new DocumentLoader(ctx, config.Filter));

How do I change Closure Compiler compile options not exported to command line?

I found that some options in CompilerOption are not exported to the command line.
For example, alias all strings is available in the Closure Compiler's Java API CompilerOption but I have no idea how set this in the command line.
I know I can create a new java class, like:
Compiler c = new Compiler();
ComppilerOptions opt = new ComppilerOptions();
opt.setAliasAllString(true);
c.compile(.....);
However I have to handle the command line args myself.
Any simple idea?
============================
In order to try the alias all string option, I write a simple command line application based on compiler.jar.
However I found that, the result I got when open the alias all string is not what I expected.
For example:
a["prototype"]["say"]=function(){
var a="something string";
}
Given the above code, the something string will be replaced by a variable like this:
var xx="something string";
....
var a=xx;
....
This is fine, but how about the string "say"? How does the closure compiler know this should be aliased(replace it use variable) or exported(export this method)?
This is the compiled code now:
a.prototype.say=function(){....}
It seems that it export it.
While I want this:
var a="prototype",b="say",c="something string";
xx[a][b]=function(){.....}
In fact, this is the google_map-like compilation.
Is this possible?
Not all options are available from the command line - this includes aliasAllStrings. For some of them you have the following options:
Build a custom version of the compiler
Use the Java API (see example).
Use plovr
Getting the same level of compression and obfuscation as the Maps API requires code written specifically for the compiler. When properly written, you'll see property and namespace collapsing, prototype aliasing and a whole host of others. For an example of the style of code that will optimize that way, take a look at the Closure Library.
Modifying http://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/javascript/jscomp/CompilationLevel.java?r=706 is usually easy enough if you just want to play with something.
Plovr (a Closure build tool) provides an option called experimental-compiler-options, which is documented as follows:
The Closure Compiler contains many options that are only available programmatically in Java. Many of these options are experimental or not finalized, so they may not be a permanent part of the API. Nevertheless, many of them will be useful to you today, so plovr attempts to expose these the experimental-compiler-options option. Under the hood, it uses reflection in Java, so it is fairly hacky, but in practice, it is a convenient way to experiment with Closure Compiler options without writing Java code.

How can I tell the Closure Compiler not to rename an inner function using SIMPLE_OPTIMIZATIONS?

How can I tell the Closure Compiler not to rename an inner function? E.g., given this code:
function aMeaninglessName() {
function someMeaningfulName() {
}
return someMeaningfulName;
}
...I'm fine with Closure renaming the outer function (I actively want it to, to save space), but I want the function name someMeaningfulName left alone (so that the name shown in call stacks for it is "someMeaningfulName", not "a" or whatever). This despite the fact that the code calling it will be doing so via the reference returned by the factory function, not by the name in the code. E.g., this is purely for debugging support.
Note that I want the function to have that actual name, not be anonymous and assigned to some property using that name, so for instance this is not a duplicate of this other question.
This somewhat obscure use case doesn't seem to be covered by either the externs or exports functionality. (I was kind of hoping there'd be some annotation I could throw at it.) But I'm no Closure Compiler guru, I'm hoping some of you are. Naturally, if there's just no way to do that, that's an acceptable answer.
(The use case is a library that creates functions in response to calls into it. I want to provide a version of the library that's been pre-compressed by Closure with SIMPLE_OPTIMIZATIONS, but if someone is using that copy of the library with their own uncompressed code and single-stepping into the function in a debugger [or other similar operations], I want them to see the meaningful name. I could get around it with eval, or manually edit the compressed result [in fact, the context is sufficiently unique I could throw a sed script at it], but that's awkward and frankly takes us into "not worth bothering" territory, hence looking for a simple, low-maintenance way.)
There is no simple way to do this. You would have to create a custom subclass of the CodingConvention class to indicate that your methods are "local" externs (support for this was added to handle the Prototype library). It is possible that InlineVariables, InlineFunctions, or RemoveUsedVariables will still try to remove the name and would also need to be fixed up.
Another approach is to use the source maps to remap the stack traces to the original source.
read the following section
https://developers.google.com/closure/compiler/docs/api-tutorial3#export
Two options basically, use object['functionName'] = obj.functionName or the better way
use exportSymbol and exportProperty both on the goog object, here is the docs link for that
http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html
-- edit
ah, i see now, my first answer is not so great for you. The compiler has some interesting flags, the one which might interest you is DEBUG, which you can pass variables into the compiler which will allow you to drop some debugging annotations in via logging or just a string which does nothing since you are using simple mode.
so if you are using closure you can debug against a development version which is just a page built with dependiencies resolved. we also the drop the following in our code
if(DEBUG){
logger.info('pack.age.info.prototype.func');
}

Resources