There are some differences between SlimerJS and PhantomJS 1.9.x although we tried to implement the same behaviors of PhantomJS APIs.
PhantomsJS is built on top of Webkit and JavascriptCore (like Safari) and SlimerJS is built on top of Gecko and SpiderMonkey (like Firefox).
Many of differences come from differences between these two web platforms, Webkit and Gecko. So we couldn't suppress these differences in SlimerJS. There are also some few differences that exist in the API because it was our choice.
So here are some of these differences. This list is not exhaustive of course! We found most of them during the port of CasperJS on SlimerJS.
- SlimerJS' javascript engine implements most of ES6 features
- The property
name
on JS functions is read only in Gecko. - Error message for a
ReferenceError
is not strictly equal between Gecko and Webkit. - The name of an exception for a syntax error is
"SyntaxError"
in gecko, and"SYNTAX_ERR"
for Webkit - PhantomJS has hacked the
Error
object in QTWebkit, to add astackArray
property. Of course, this property does not exist in the SpiderMonkey implementation, but it has a stack property. So you should use it ifstackArray
is not present.
- In Gecko, the value of a
<input type=file>
is only the filename. PhantomJS generates a path starting withc:\\fakepath\\
. - Contrary to PhantomJs/Webkit, Gecko does not support the non-standard property
innerText
on DOM elements. - Using
typeof
on a window object returns"window"
with PhantomJS/Webkit, and"domwindow"
in Gecko. "javascript:"
links are executed asynchronously in Gecko- Gecko does not support these non-standard properties on events:
x
andy
The equivalent standard properties areclientX
andclientY
. - Changing the viewport is done asynchronously in Gecko, so
webpage.viewportSize
is done asynchronously in SlimerJS - A
content
variable exists in SlimerJS, in scripts, because of window.content <https://developer.mozilla.org/en-US/docs/Web/API/Window.content>. Remember that a script is executed in the context of aabout:blank
page.
- It seems that Gecko has a different behavior than Phantomjs's webkit on some HTTP response with code 102, 118 and 408. It response.status is null, it is probably because of one of this response code.
- PhantomJS doesn't do redirections, whereas SlimerJS does.
- When PhantomJS receives a redirection as HTTP response, it doesn't call the
onResponseReceive
with thestart
status. SlimerJS calls it. - When doing manual redirections (by calling
changeUrl()
on the request object), SlimerJS (Gecko) create a request, then cancels it and create a second request, so youronResponseReceive
is called for the two requests.. PhantomJS just reuse the same request. - If the url given to webpage.open() is malformed, PhantomJS calls the callback with "success" whereas SlimerJS calls it with "fail"
- The main script is considered as a module, for more security and to be compatible with Mozilla modules. So
this
is notwindow
and there is anexports
object. webpage.sendEvent()
for key events is more consistent. In PhantomJS, there are several issues.webpage.open()
returns a promise. It's easier to chain things executed asynchronously- The call of
webpage.open()
(oropenUrl()
), in PhantomJS, ends when the load is starting. But in SlimerJS it ends almost immediately because it should open a real window before the loading and it is done asynchronously. So probably some properties will not be available immediately after the call ofopen()
in SlimerJS. - It seems that the call of listeners during the page loading is not done at the same step between PhantomJS and SlimerJS. Implementation in PhantomJS is a bit obscure.
webpage.open()
andopenUrl()
support only "GET" and "POST" operation in SlimerJS, no "PUT" nor "DELETE" operations.- The webserver object has more methods to configure it easily
toString()
on a webpage object returns "qtruntimeobject" in PhantomJS and "Object" in SlimerJS. There are no way to change this behavior in SlimerJS (it is developped in pure Javascript). So to test if a given object is awebpage
object in SlimerJS, you should test a specific property__type
. Its value is then "qtruntimeobject" (to mimic PhantomJS).- PhantomJS has a strange behavior on
fs.read()
: it seems it reads files always as binary files. However SlimerJS'sfs.read()
strictly respect the 'b' flag parameter. - The module system has a different behavior than PhantomJS's one
- global variables declared in the main script are not accessible in
modules loaded with
require
- Modules are completely impervious. They are executed in a truly javascript sandbox
- Modules must be files, not folders.
- SlimerJS provides
require.paths
- global variables declared in the main script are not accessible in
modules loaded with
phantom.exit()
orslimer.exit()
is done asynchronously. Your script may continue after- the call of these methods. You can use
slimer.isExiting()
to control your processing.
- The callback
webpage.onNavigationRequest
receives bad parameters. Don't rely on thenavigationType
and theisMainFrame
values (because of some limitations in the Gecko API). - Callbacks
webpage.onLoadStarted
andwebpage.onLoadFinished
receive additional parameters in SlimerJS (the url, a boolean indicated if it is in a frame...) - You can output binary content on the standard output stream (weither with
fs.open('/dev/stdout')
,webpage.render('/dev/stdout')
orsystem.stdout
)
Some few PhantomJS features are still missing in SlimerJS. See release notes.