-
Notifications
You must be signed in to change notification settings - Fork 851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide console API in shell. #1103
Conversation
d0ac17b
to
6f29fa5
Compare
Great work! As for the reformatting of Globals.java: we tend to do reformatting in a separate commit/PR, so formatting and actual changes are separated. Any chance you can create a separate PR for that? As for the console implementation: seems like the implementation is tied directly to the Shell via the print method, from which I assume the console implementation cannot be used by embeddings that don't use the Shell? |
PR #1104 is created for reformatting I've thought about using |
As for how to enable the console in an embedded Rhino: the embedder can can the init method themselves I think the more important part is how to allow the embedder to control how an 'output' is being handled For the Shell is being dealt with by calling the println method. In an embedding it might have to be handled by calling the appropriate method(s) of the used log library So i think maybe define some interface and require to pass an instance of a class implementing that interface to the init method of the NativeConsole? That way what's being done with the output is decoupled from the console implementation |
Exactly what such interface should look like I'm not exactly sure: some implementations might want the raw data (for example an object passed as argument to console.log) while others would rather have the entire data as an already formatted string And some might want to know the log level. Btw: another option instead of an interface would be to provide a basic implementation based on System.out.println and just extend NativeConsole and override that implementation with whatever is desired |
How about the following solution. First, when and where should I put the
|
I would say neither of the two options you mentioned. We can hadcode the console to be available in the Shell, but that's about it. For all other embeddings, it should be up to the embedder whether to include it or not and I think a feature flag is not really necesarry, an embedding has code already to initialize the embedding, like setting the language level etc. Adding a call there to initialize the console if they want is sufficient imho.
Why not just |
Very nice PR! |
I have made some changes in order to make printer customizable in embedding usage.
Yes, I need. I'll write them later. |
I think it'd be great to have "console"! But I do think that we should only have it in Global (which makes it part of the shell) and:
|
As discussed in #1012 I think the plugable printer needs to take an If the first argument is a string, then NativeConsole can perform the substitutions, but any remaining arguments that are not used in the substitution or all of the arguments if the first is not a string should be passed to the printer to handle as appropriate. Some printers may want to display debug level detail (possibly in a GUI like the Chrome and Firefox consoles) for nested objects rather than just performing a toString operation on them. A Context object should also be passed to facilitate accessing the (nested) object properties. That doesn't preclude a function that would return an implementation that would do that basic conversion. NativeConsole.ConsolePrinter createToStringConsolePrinter(OutputStream trace, OutputStream debug, OutputStream info, OutputStream warn, OutputStream error) |
|
I've changed args of print to Object[]. |
8905c3f
to
bd692bf
Compare
Thanks! Can you follow the comments above and get rid of the now-obsolete "idswitch" stuff? You can look at any of the existing classes for an example. Also, it'd be great to take a look at the man page (the file is rhino/man.1) and see if we can update it to mention that the "console" object is now supported. |
return "Console"; | ||
|
||
case Id_trace: | ||
printer.print(cx, scope, Level.TRACE, args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't console.trace() automatically send the current stacktrace as the first entry in the args object[] to the printer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about the latest code which passes ScriptStackElement[] stack
after Object[] args
.
@MaxisTekfield any chance you could followup on the previous two comments on this PR? would be nice to get this ready to be merged |
Got it. These takes more time to make changes. I'll make them done in next few days. |
3042569
to
ae1b6a9
Compare
|
||
case "%d": | ||
case "%i": | ||
double number = ScriptRuntime.toNumber(args, argIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BigInt will cause an error.
console.log('%d', 10n)
// js: uncaught JavaScript runtime exception: TypeError: Cannot convert BigInt to a number
The specifications are as follows.
https://console.spec.whatwg.org/#formatting-specifiers
%d or %i | Element which substitutes is converted to an integer | %parseInt%(element, 10)
The implementation are as follows.
V8 (Node.js v14.17.0)
console.log('%d', 10n) // 10n
console.log('%f', 10n) // NaN
SpiderMonkey (Firefox/97.0) (ref. https://bugzilla.mozilla.org/show_bug.cgi?id=1753682)
console.log('%d', 10n) // undefined
console.log('%f', 10n) // undefined
I didn't know what was right at the time of %f
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
console.log('%d', Symbol.iterator)
// js: uncaught JavaScript runtime exception: TypeError: The object is not a number
According to the specification, it seems that Symbol should be converted to NaN.
https://console.spec.whatwg.org/#formatter
If Type(current) is Symbol, let converted be NaN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even %o
or %O
will cause an error.
console.log('%o', { a: 0n })
// js: uncaught JavaScript runtime exception: TypeError: Do not know how to serialize a BigInt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got a syntax error. How to represent a BigInt in rhino shell?
js> print(10n);
js: "<stdin>", line 10: missing ) after argument list
js: print(10n);
js: .........^
js: "<stdin>", line 10: Compilation produced 1 syntax errors.
js> console.log("%d", 10n);
js: "<stdin>", line 12: missing ) after argument list
js: console.log("%d", 10n);
js: .....................^
js: "<stdin>", line 12: Compilation produced 1 syntax errors.
js>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add -version 200
.
$ java -jar buildGradle/libs/rhino-1.7.15-SNAPSHOT.jar -version 200
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even
%o
or%O
will cause an error.console.log('%o', { a: 0n }) // js: uncaught JavaScript runtime exception: TypeError: Do not know how to serialize a BigInt
I think this is not the problem of console. This TypeError is thrown at org.mozilla.javascript.NativeJSON#str
if (value instanceof Number) {
if (value instanceof BigInteger) {
throw ScriptRuntime.typeErrorById("msg.json.cant.serialize", "BigInt");
}
// ...
}
This problem also occurs when using JSON.stringify
js> JSON.stringify({a: 10n});
js: uncaught JavaScript runtime exception: TypeError: Do not know how to serialize a BigInt
at (unknown):9
Should we modify org.mozilla.javascript.NativeJSON#str
in order to output BigInt when using console and JSON.stringify APIs? Maybe starting another issue is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I do. It is a specification of ECMA262 that JSON.stringify
will error on BigInt.
https://262.ecma-international.org/12.0/#sec-serializejsonproperty
- If Type(value) is BigInt, throw a TypeError exception.
Even in Node.js, using %j
will result in an error.
console.log('%j', 10n)
// Uncaught TypeError: Do not know how to serialize a BigInt
console.log('%o', 10n) // 10n
Other than that, JSON.stringify
will cause an error with circular references.
var o = {};
o.o = o;
JSON.stringify(o);
// js: uncaught JavaScript runtime exception: TypeError: Cyclic org.mozilla.javascript.NativeObject value not allowed.
If you definitely don't want to generate errors, you should use a method other than JSON.stringify
to display the data. However, for now, I think it is enough to catch the exception and fall back to ScriptRuntime.toString
.
9c4eb6c
to
178d18c
Compare
178d18c
to
868d043
Compare
printer.print(cx, scope, level, null, new String[] {msg}); | ||
} | ||
|
||
public static String format(Context cx, Scriptable scope, Object[] args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have had some corrections made, could you write tests for them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
13192a2 Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's hard to cover all those specifications, especially those who have different behaviors in different runtime engines.
Thanks for all the work on this -- I hope that we can keep making it more complete. I'm going to ask for a few more things, but I think that sooner or later we can get this working... First, can you move NativeConsole to the org.mozilla.javascript.tools package in the "toolsrc" tree? The reason is that everything like this, that prints to standard output for example, should be in that separate package so that it doesn't clutter up the main "src" tree which IMO should just be the basic JavaScript engine. The rest of the shell stuff works this way. Second, can we get at least some basic test coverage of the basic functions? It looks like some of it is there (thanks!) and some will be hard to test, like the "time" function, so there at least a test to prove it doesn't bomb out would be enough. Finally, it seems like "console" could just be a garden-variety object (created using cx.newObject for example) and each property could be an instance of LambdaFunction. That might avoid all of the complicated IdScriptableObject stuff. But I can look at that later, it's just an idea to simplify things. |
Am not sure if this is a good idea: the console is (imho) something embedders and script-engine users might also want to use. Making them require to use the bundle that includes all the tools would not be so great I think |
Emm, I don't know what should I do. |
Deno and Node.js seem to be able to use |
I would be concerned about this being in the main package if it did things like open files or execute processes like our "Global" object does. Since it doesn't, and if others disagree, then I'm fine with having it in the main package where it is in this PR. So then the only remaining thing is to see if we can at least have a sanity test of each function in the API. Thank you for all the work on this! |
More tests added. |
Thanks for all the work. Since this requires a merge and has many commits, I'm going to close this PR manually and merge the code into master. |
Tnx @MaxisTekfield for all your work! |
As #1012 says, I've been trying to implement the
console
API in shell.PR #1104 is prerequisite as p-bakker said. After #1104 is merged. I'll rebase this PR.
Basic usage:
Closes #1012