Why is toString of JavaScript function implementation-dependent? - javascript

From the EcmaScript 5 specification
15.3.4.2 Function.prototype.toString( )
An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.
Why is it implementation-dependent? It shouldn't be too hard to make it output standardized string consisting of the original code of the function. Also the reasons that I can come up with such as optimization, doesn't seem to be too heavily used as pretty much all the browsers give the original code as result of toString.
If the toString wouldn't be implementation-dependent and thus would be standardized to be the original code for function (with the new lines etc. handled on standard way), wouldn't it make it possible to include the functions on JSON?
I do realize that the JSON, despite its name, is independent of JavaScript and thus the functions shouldn't be part of it. But this way the functions could in theory be passed with it as strings, without losing the cross-browser support.

Internally, Function.prototype.toString() has to get the function declaration code for the function, which it may or may not have. According to the MDN page, FF used to decompile the function, and now it stores the declaration with the function, so it doesn't have to decompile it.
Since Gecko 17.0 (Firefox 17 / Thunderbird 17 / SeaMonkey 2.14),
Function.prototype.toString() has been implemented by saving the
function's source. The decompiler was removed
*https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString
Decompiling it requires extra work. Storing it requires extra memory. A given ECMAscript implementation may have different resource requirements.
Further, if it is decompiled, that is dependent on how it was stored in the first place. An engine may be unable to return comments in the original, because it didn't store them when the function was evaluated. Or whitespace/newlines might be different if the engine collapsed them. Or the engine may have optimized the code, such as by ignoring unreachable code, making it not possible to return that code back in the toString() call.
...some engines omit newlines. And others omit comments. And others
omit "dead code". And others include comments around (!) function. And
others hide source completely...
*http://perfectionkills.com/state-of-function-decompilation-in-javascript/
These are just a few reasons why Function.prototype.toString() is implementation dependent.

Related

Why does V8 isValidSmi native function returns true on float number?

Don't understand why V8 native function %isValidSmi(2.2) returns true in Nodejs.
NodeJS version: 8.9.4
I thought SMI number it is something similar to int32
(V8 developer here.) In short, because it performs a NumberToInt32 conversion before looking at the value.
You might say that that's a surprising implementation choice, and indeed I can't tell you why it's been done that way. Apparently for the intended use cases of this internal helper, the resulting behavior was acceptable or even desired.
"internal helper" is the key term there. V8's internal "runtime functions" are not intended for public usage, as such they're not exposed by default, they're not specified or standardized or documented, and they're typically rather restrictive regarding the arguments they accept (for example, %IsValidSmi({}) will crash rather than returning false, because it's not designed to handle arbitrary inputs). As a V8 developer, you just have to look at the code to see if a given runtime function does what you need, and as a non-V8-developer, you're not supposed to have a reason to care :-)
Such implementation details aside, your understanding is correct that 2.2 is not a valid Smi. It just so happens that %IsValidSmi() is not a suitable way to determine that. FWIW, there's also %IsSmi(value), which checks whether value is currently internally represented as a Smi -- which is notably different from a number that could be represented as a Smi.
Either way, our official recommendation is that your code should not care which values V8 chooses to represent as Smis. In particular, this also changes over time, both over the course of running a single program, and also as V8 versions change.

howto get a JSON (or equivalent) representation of a JavaScript *code file* (the code, as a string, in input)?

Everything is in the title! ^^
I know about some SourceCode browsers for js; they usually permit to find some small stuff when the code relatively abides in structure by the current informal js coding norm.
(eg, use of the new operator, functions mainly created through definitions (F foo() {}) rather than through expression statements or literal objects (var foo = F(){}, { foo: F(){} }), etc; norm i precisely happen not to do adhere to).
but, what would truly interest me would be a full parsing of the code, a tool returning, for example, a JSON file containing the whole code, that is, all the statements, function calls, even the parameters of the function calls (usually forgotten in js sourcebrowsers, because those objects are de facto anonymous objects/functions; however they are precisely abundantly used in functional-like programming, and thus get invisible to all source browsers i met)
the purpose of course would be to create from that JSONized code, my own source browser, that would hopefully go farther than the average one, and would meet my needs to browse my code easily, see also easily, which variable is defined where, and some other stuff that might enhance my coding experience.
anyhow; i'm not particularly attached to the JSON format, altho of course since i'd code my source browser in JS, it'd be the immediate easy input, but any other data representation format is OK, what matters is a parser that transforms code into a mouthpiece object¹.
Anything looking and doing sth like that (eg a L/Hinter with a more verbose and informative output, or else) is welcome ;)
thanks in advance :)
¹ "object": an object as JS defines it, ie, an abstract data alike or identical to a dictionary; not an object as class-based OO languages define it (class instances)
I think you are searching for a standard to represent javascript code as an abstract syntax tree (AST). There is a widely used standard for javascript AST and it is called ESTree. There is an active community supporting the standardization project and it is updated for new versions of javascript.
Alternatively, there is also Shift AST that offers a slightly different standard AST, and it has an online real time parsing tool.
Implementations of AST generators usually provide a Parser with a parse() method that take your javascript code as a string parameter value, and they return an abstract syntax tree object as defined by the standard.
For example passing this code:
c = a + b;
Will produce this AST:
type: "Script"
directives:[]
statements:
0:
type: "ExpressionStatement"
expression:
type: "AssignmentExpression"
binding:
type: "BindingIdentifier"
name: "c"
expression:
type: "BinaryExpression"
left:
type: "IdentifierExpression"
name: "a"
operator: "+"
right:
type: "IdentifierExpression"
name: "b"
Finally, there are code generators to perform the reverse procedure: when having an AST and wanting to generate javascript code from that.
An updated and well maintained implementation of an ESTree parser can be found here.

Does JSON.parse() use eval() internally? [duplicate]

This question already has answers here:
What is JSON.parse written in / Is it open source?
(4 answers)
Closed 9 years ago.
Does JSON.parse in modern browsers use eval() internally for evaluating and executing the dynamic code?
Because I have been looking through Douglas Crockford's JSON library. It also uses eval() when using parse() but after preprocessing prior to the actual evaluation. Such as:-
A wall against Unicode characters in the code.
A code shows malicious intent.
Do the modern browsers which supports JSON.parse natively perform this or they follow other protocols?
No, JSON.parse() doesn't Use eval()
This is by design, as eval() being able to execute any arbitrary JavaScript code you feed it, it could execute things you wouldn't want it to. So JSON.parse() does what it says on the tin: it actually parses the whole string and reconstructs and entire object tree.
JSON.parse is usually delegated to an internal function implemented with "native" code, where "native" means whatever is considered "native" in the context of your browser's javascript engine (could be compiled machine code, could be bytecode for a VM, etc...). I don't think there's any strong requirement on that.
Differences in the Implementations?
JSON (the notation) itself is codified by the RFC4627.
Regarding the implemetation of the JSON object and its methods, all modern browsers implementing should behave the same, as they should follow the same specifications for ECMAScript 5's JSON object. However, there's always the chance for potential defects. For instance, V8 originally contained this nasty bug.
Also, note that the implementation listed in comments above are for you to add JSON.parse() support to browsers that do not support it natively (also known as "these damn old browsers you sometimes need to support"). But it doesn't mean that it's necessarily how they implemented it.
For instance, for Google's V8 implementation used in Chrome, see json.js which invokes native code from json_parser.h.
It would be a very funny thing to do, if you think about it.
To understand why, see if this analogy helps: you're traveling with your boss to a country where you speak the language but she doesn't. Since you're fluent, you will serve two roles: as her assistant (doing tasks for her) as well as her translator (telling her what things mean).
So you have these two jobs, which are complementary. Your boss could tell you to do something--in any language you both understand (say, English)--as well as ask you to tell her what something says, like a sign or a document. She could even do both: hand you a set of instructions written in this other language and say, "This was given to me by someone I trust. Please do everything it says here."
In this analogy, reading signs or documents to your boss is like JSON.parse. Your boss handing you instructions and telling you to do everything they say is like eval.
If JavaScript engines used eval internally for JSON.parse, that would be analogous to your boss asking you what a document says, and you choosing to act out everything written in the document in order to explain it to her. Instead of just reading it.

Is it acceptable style for Node.js libraries to rely on object key order?

Enumerating the keys of javascript objects replays the keys in the order of insertion:
> for (key in {'z':1,'a':1,'b'}) { console.log(key); }
z
a
b
This is not part of the standard, but is widely implemented (as discussed here):
ECMA-262 does not specify enumeration order. The de facto standard is to match
insertion order, which V8 also does, but with one exception:
V8 gives no guarantees on the enumeration order for array indices (i.e., a property
name that can be parsed as a 32-bit unsigned integer).
Is it acceptable practice to rely on this behavior when constructing Node.js libraries?
Absolutely not! It's not a matter of style so much as a matter of correctness.
If you depend on this "de facto" standard your code might fail on an ECMA-262 5th Ed. compliant interpreter because that spec does not specify the enumeration order. Moreover, the V8 engine might change its behavior in the future, say in the interest of performance, e.g.
Definitely do not rely on the order of the keys. If the standard doesn't specify an order, then implementations are free to do as they please. Hash tables often underlie objects like these, and you have no way of knowing when one might be used. Javascript has many implementations, and they are all competing to be the fastest. Key order will vary between implementations, if not now, then in the future.
No. Rely on the ECMAScript standard, or you'll have to argue with the developers about whether a "de facto standard" exists like the people on that bug.
It's not advised to rely on it naively.
You should also do your best to stick to the spec/standard.
However there are often cases where the spec or standard limits what you can do. I'm not sure in programming I've encountered many implementations that deviate or extend the specification often for reasons such as the specification doesn't cater to everything.
Sometime people using specifics of an implementation might have test cases for that, though it's hard to make a reliable test case for beys being in order. It most succeed by accident or rather it's difficult behavior to reliably produce.
If you do rely on an implementation specific then you must document that. If your project requires portability (code to run on other people's setups out of your control and you want maximum compatibility) then in this case it's not a good idea to rely on an implementation specific such as key order.
Where you do have full control of the implementation being used then it's entirely up to you which implementation specifics you use while keeping in mind you may be forced to cater to portability due to the common need or desire to upgrade implementation.
The best form of documentation for cases like this is inline, in the code itself, often with the intention of at least making it easy to identify areas to be changed should you switch from an implementation guaranteeing order to one not doing so.
You can make up the format you like but it can be something like...
/** #portability: insertion_ordered_keys */
for(let key in object) console.log();
You might even wrap such cases up in code:
forEachKeyInOrderOfInsertion(object, console.log)
Again, likely something less overly verbose but enough to identify cases dependent on that.
For where your implementation guarantees key order you're just trans late that to the same as the original for.
You can use a JS function for that with platform detection, templating like CPP, transpiling, etc. You might also want to wrap the object creation and to be very careful about things crossing boundaries. If something loses order before reaching you (like JSON decode of input from a client over the network) then you'll likely not have a solution to that solely withing your library, this can even be just if someone else is calling your library.
Though you'll likely not need those, just make cases where you do something that might break later as a minimum and document that potential exists.
An obvious exception to that is if the implementation guarantees consistency. In that case you will probably be wasting your time decorating everything if it's not really a variability and is already documented via the implementation. The implementation often is a spec or has its own, you can choose to stick to that rather than a more generalised spec.
Ultimately in each case you'll need to make a judgement call, you may also choose to take a chance. As long as you're fully aware of the potential problems including the potential of wasting time avoiding problems you wont necessarily actually have, that is you know all the stakes and have considered your circumstances, then it's up to you what to do. There's no "should" or "shouldn't", it's case specific.
If you're making node.js public libraries or libraries to be widely distributed beyond the scope of your control then I'd say it's not good to rely on implementation specifics. Instead at least have a disclaimer with the release notes that the library is only catering to your stack and that if people want to use it for others then can fix and put in a pull request. Otherwise if not documented, it should be fixed.

subtle differences between JavaScript and Lua [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I simply love JavaScript. It's so elegant.
So, recently I have played with Lua via the löve2d framework (nice!) - and I think Lua is also great. They way I see it, those two languages are very similar.
There are obvious differences, like
syntax
problem domain
libraries
types (a bit)
but which are the more subtle ones? Is there anything a JavaScript coder would take for granted that works in Lua just slightly different? Are there any pitfalls that may not be obvious to the experienced coder of one language trying the other one?
For example: in Lua, arrays and hashes are not separate (there are only tables) - in JavaScript, they are numerical Arrays and hashed Objects. Well, this is one of the more obvious differences.
But are there differences in variable scope, immutability or something like this?
Some more differences:
Lua has native support for coroutines.
UPDATE: JS now contains the yield keyword inside generators, giving it support for coroutines.
Lua doesn't convert between types for any comparison operators. In JS, only === and !== don't type juggle.
Lua has an exponentiation operator (^); JS doesn't. JS uses different operators, including the ternary conditional operator (?: vs and/or), and, as of 5.3, bitwise operators (&, |, etc. vs. metamethods ).
UPDATE: JS now has the exponentiation operator **.
JS has increment/decrement, type operators (typeof and instanceof), additional assignment operators and additional comparison operators.
In JS, the ==, ===, != and !== operators are of lower precedence than >, >=, <, <=. In Lua, all comparison operators are the same precedence.
Lua supports tail calls.
UPDATE: JS now supports tail calls.
Lua supports assignment to a list of variables. While it isn't yet standard in Javascript, Mozilla's JS engine (and Opera's, to an extent) has supported a similar feature since JS 1.7 (available as part of Firefox 2) under the name "destructuring assignment". Destructuring in JS is more general, as it can be used in contexts other than assignment, such as function definitions & calls and loop initializers. Destructuring assignment has been a proposed addition to ECMAScript (the language standard behind Javascript) for awhile.
UPDATE: Destructuring (and destructuring assignment) is now part of the spec for ECMAScript - already implemented in many engines.
In Lua, you can overload operators.
In Lua, you can manipulate environments with getfenv and setfenv in Lua 5.1 or _ENV in Lua 5.2 and 5.3.
In JS, all functions are variadic. In Lua, functions must be explicitly declared as variadic.
Foreach in JS loops over object properties. Foreach in Lua (which use the keyword for) loops over iterators and is more general.
UPDATE: JS has Iterables now too, many of which are built into the regular data structures you'd expect, such as Array. These can be looped over with the for...of syntax. For regular Objects, one can implement their own iterator functions. This brings it much closer to Lua.
JS has global and function scope. Lua has global and block scope. Control structures (e.g. if, for, while) introduce new blocks.
Due to differences in scoping rules, a closure's referencing of an outer variable (called "upvalues" in Lua parlance) may be handled differently in Lua and in Javascript. This is most commonly experienced with closures in for loops, and catches some people by surprise. In Javascript, the body of a for loop doesn't introduce a new scope, so any functions declared in the loop body all reference the same outer variables. In Lua, each iteration of the for loop creates new local variables for each loop variable.
local i='foo'
for i=1,10 do
-- "i" here is not the local "i" declared above
...
end
print(i) -- prints 'foo'
The above code is equivalent to:
local i='foo'
do
local _i=1
while _i<10 do
local i=_i
...
_i=_i+1
end
end
print(i)
As a consequence, functions defined in separate iterations have different upvalues for each referenced loop variable. See also Nicolas Bola's answers to Implementation of closures in Lua? and "What are the correct semantics of a closure over a loop variable?", and "The Semantics of the Generic for".
UPDATE: JS has block scope now. Variables defined with let or const respect block scope.
Integer literals in JS can be in octal.
JS has explicit Unicode support, and internally strings are encoded in UTF-16 (so they are sequences of pairs of bytes). Various built-in JavaScript functions use Unicode data, such as "pâté".toUpperCase() ("PÂTÉ"). Lua 5.3 and up have Unicode code point escape sequences in string literals (with the same syntax as JavaScript code point escape sequences) as well as the built-in utf8 library, which provides basic support for the UTF-8 encoding (such as encoding code points into UTF-8 and decoding UTF-8 into code points, getting the number of code points in a string, and iterating over code points). Strings in Lua are sequences of individual bytes and can contain text in any encoding or arbitrary binary data. Lua does not have any built-in functions that use Unicode data; the behavior of string.upper depends on the C locale.
In Lua, the not, or, and keywords are used in place of JS's !, ||, &&.
Lua uses ~= for "not equal", whereas JS uses !==. For example, if foo ~= 20 then ... end.
Lua 5.3 and up use ~ for binary bitwise XOR, whereas JS uses ^.
In Lua, any type of value (except nil and NaN) can be used to index a table. In JavaScript, all non-string types (except Symbol) are converted to strings before being used to index an object. For example, after evaluation of the following code, the value of obj[1] will be "string one" in JavaScript, but "number one" in Lua: obj = {}; obj[1] = "number one"; obj["1"] = "string one";.
In JS, assignments are treated as expressions, but in Lua they are not. Thus, JS allows assignments in conditions of if, while, and do while statements, but Lua does not in if, while, and repeat until statements. For example, if (x = 'a') {} is valid JS, but if x = 'a' do end is invalid Lua.
Lua has syntactic sugar for declaring block-scoped function variables, functions that are fields, and methods (local function() end, function t.fieldname() end, function t:methodname() end). JS declares these with an equals sign (let funcname = function optionalFuncname() {}, objectname.fieldname = function () {}).
A couple of subtle differences that will catch you out at least once:
Not equal is spelled ~= in Lua. In JS it is !=
Lua arrays are 1-based - their first index is 1 rather than 0.
Lua requires a colon rather than a period to call object methods. You write a:foo() instead of a.foo() †
† you can use a period if you want, but have to pass the self variable explicitly. a.foo(a) looks a bit cumbersome. See Programming in Lua for details.
To be honest it would be easier to list the things which are common to Javascript and Lua than to list the differences. They are both dynamically-typed scripting languages, but that's about as far as you can go really. They have totally different syntax, different original design goals, different modes of operation (Lua is always compiled to bytecode and run on the Lua VM, Javascript varies), the list goes on and on.
JavaScript arrays and objects are closer than you might think. You can use array notation to get at the elements of either of them, and you can add non-numeric indices to arrays. Individual array elements can hold anything, and the array can be sparse. They are nearly identical cousins.
I liked this question and the answers provided. Additional reasons the two languages seem more alike than not to me:
Both
assign functions to variables,
can build functions on the fly,
and define closures.
Off the top of my head
Lua ...
supports coroutines
has no restriction to just string/number as key for a table. Everything works.
the error handling is somewhat clumsy. Either you don't handle anything or use the pcall method
I think I read something about differences in the lexical scope and that Lua has the better one.
If I recall correctly regular expression support in lua is limited
Lua and JavaScript are both prototype base languages.
A test reveals that current Javascript also returns objects, or at least strings from logic expressions like lua does:
function nix(){
alert(arguments[0]||"0");
}
nix();

Categories

Resources