Skip to content

Commit

Permalink
Implement Navigator to-spec
Browse files Browse the repository at this point in the history
Adds a variety of missing properties to Navigator:

- appCodeName, product, productSub, vendor, and vendorSub from NavigatorID
- language and languages from NavigatorLanguage
- onLine from NavigatorOnLine
- javaEnabled() from NavigatorPlugins (fixes #1467)

Also removes the nonstandard navigator.noUI property.

We now emulate Chrome a bit more closely: we follow the spec with "navigator compatibility mode" of Chrome, which locks down appName, platform, and version to be more browser-like instead of Node.js-like. The default userAgent similarly gains a suffix "AppleWebKit/537.36 (KHTML, like Gecko)".
  • Loading branch information
domenic committed May 7, 2016
1 parent c2c3af9 commit 306805a
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 55 deletions.
3 changes: 2 additions & 1 deletion lib/jsdom.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ function setGlobalDefaultConfig(config) {

config.strictSSL = config.strictSSL !== undefined ? config.strictSSL : true;

config.userAgent = config.userAgent || "Node.js (" + process.platform + "; U; rv:" + process.version + ")";
config.userAgent = config.userAgent ||
`Node.js (${process.platform}; U; rv:${process.version}) AppleWebKit/537.36 (KHTML, like Gecko)`;
}

function getConfigFromArguments(args) {
Expand Down
25 changes: 6 additions & 19 deletions lib/jsdom/browser/Window.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const idlUtils = require("../living/generated/utils");
const createFileReader = require("../living/file-reader");
const createXMLHttpRequest = require("../living/xmlhttprequest");
const Document = require("../living/generated/Document");
const Navigator = require("../living/generated/Navigator");
const reportException = require("../living/helpers/runtime-script-errors");

// NB: the require() must be after assigning `module.exports` because this require() is circular
Expand Down Expand Up @@ -104,6 +105,8 @@ function Window(options) {

///// GETTERS

const navigator = Navigator.create([], { userAgent: options.userAgent });

define(this, {
get length() {
return window._length;
Expand Down Expand Up @@ -131,6 +134,9 @@ function Window(options) {
},
get history() {
return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._history);
},
get navigator() {
return navigator;
}
});

Expand Down Expand Up @@ -336,25 +342,6 @@ function Window(options) {
}

define(this, {
navigator: {
get userAgent() {
return options.userAgent;
},
get appName() {
return "Node.js jsDom";
},
get platform() {
return process.platform;
},
get appVersion() {
return process.version;
},
noUI: true, // TODO MAJOR https://github.com/tmpvar/jsdom/issues/1405
get cookieEnabled() {
return true;
}
},

name: "nodejs",
innerWidth: 1024,
innerHeight: 768,
Expand Down
24 changes: 24 additions & 0 deletions lib/jsdom/living/navigator/Navigator-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use strict";
const idlUtils = require("../generated/utils");
const NavigatorIDImpl = require("./NavigatorID-impl").implementation;
const NavigatorLanguageImpl = require("./NavigatorLanguage-impl").implementation;
const NavigatorOnLineImpl = require("./NavigatorOnLine-impl").implementation;
const NavigatorCookiesImpl = require("./NavigatorCookies-impl").implementation;
const NavigatorPluginsImpl = require("./NavigatorPlugins-impl").implementation;
const NavigatorConcurrentHardwareImpl = require("./NavigatorConcurrentHardware-impl").implementation;

class NavigatorImpl {
constructor(args, privateData) {
this.userAgent = privateData.userAgent;
this.languages = Object.freeze(["en-US", "en"]);
}
}

idlUtils.mixin(NavigatorImpl.prototype, NavigatorIDImpl.prototype);
idlUtils.mixin(NavigatorImpl.prototype, NavigatorLanguageImpl.prototype);
idlUtils.mixin(NavigatorImpl.prototype, NavigatorOnLineImpl.prototype);
idlUtils.mixin(NavigatorImpl.prototype, NavigatorCookiesImpl.prototype);
idlUtils.mixin(NavigatorImpl.prototype, NavigatorPluginsImpl.prototype);
idlUtils.mixin(NavigatorImpl.prototype, NavigatorConcurrentHardwareImpl.prototype);

exports.implementation = NavigatorImpl;
58 changes: 58 additions & 0 deletions lib/jsdom/living/navigator/Navigator.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
interface Navigator {
// objects implementing this interface also implement the interfaces given below
};
Navigator implements NavigatorID;
Navigator implements NavigatorLanguage;
Navigator implements NavigatorOnLine;
//Navigator implements NavigatorContentUtils;
Navigator implements NavigatorCookies;
Navigator implements NavigatorPlugins;
Navigator implements NavigatorConcurrentHardware;

[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorID {
[Exposed=Window] readonly attribute DOMString appCodeName; // constant "Mozilla"
readonly attribute DOMString appName; // constant "Netscape"
readonly attribute DOMString appVersion;
readonly attribute DOMString platform;
[Exposed=Window] readonly attribute DOMString product; // constant "Gecko"
[Exposed=Window] readonly attribute DOMString productSub;
readonly attribute DOMString userAgent;
[Exposed=Window] readonly attribute DOMString vendor;
[Exposed=Window] readonly attribute DOMString vendorSub; // constant ""

// also has additional members in a partial interface
};

[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorLanguage {
readonly attribute DOMString language;
readonly attribute FrozenArray<DOMString> languages;
};

[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorOnLine {
readonly attribute boolean onLine;
};

[NoInterfaceObject]
interface NavigatorCookies {
readonly attribute boolean cookieEnabled;
};

[NoInterfaceObject]
interface NavigatorCookies {
readonly attribute boolean cookieEnabled;
};

[NoInterfaceObject]
interface NavigatorPlugins {
// [SameObject] readonly attribute PluginArray plugins;
// [SameObject] readonly attribute MimeTypeArray mimeTypes;
boolean javaEnabled();
};

[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"use strict";
const os = require("os");

exports.implementation = class NavigatorConcurrentHardwareImpl {
get hardwareConcurrency() {
return os.cpus().length;
}
};
7 changes: 7 additions & 0 deletions lib/jsdom/living/navigator/NavigatorCookies-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use strict";

exports.implementation = class NavigatorCookiesImpl {
get cookieEnabled() {
return true;
}
};
37 changes: 37 additions & 0 deletions lib/jsdom/living/navigator/NavigatorID-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use strict";

exports.implementation = class NavigatorIDImpl {
get appCodeName() {
return "Mozilla";
}

get appName() {
return "Netscape";
}

get appVersion() {
return "4.0";
}

get platform() {
return "";
}

get product() {
return "Gecko";
}

get productSub() {
return "20030107";
}

// see Navigator constructor for userAgent

get vendor() {
return "Google Inc.";
}

get vendorSub() {
return "";
}
};
9 changes: 9 additions & 0 deletions lib/jsdom/living/navigator/NavigatorLanguage-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";

exports.implementation = class NavigatorLanguageImpl {
get language() {
return "en-US";
}

// See Navigator constructor for languages
};
7 changes: 7 additions & 0 deletions lib/jsdom/living/navigator/NavigatorOnLine-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use strict";

exports.implementation = class NavigatorOnLineImpl {
get onLine() {
return true;
}
};
7 changes: 7 additions & 0 deletions lib/jsdom/living/navigator/NavigatorPlugins-impl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use strict";

exports.implementation = class NavigatorPluginsImpl {
javaEnabled() {
return false;
}
};
1 change: 1 addition & 0 deletions scripts/webidl/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ doConversion(path.resolve(__dirname, "../../lib/jsdom/living/traversal"))
.then(() => doConversion(path.resolve(__dirname, "../../lib/jsdom/living/attributes")))
.then(() => doConversion(path.resolve(__dirname, "../../lib/jsdom/living/window")))
.then(() => doConversion(path.resolve(__dirname, "../../lib/jsdom/living/nodes")))
.then(() => doConversion(path.resolve(__dirname, "../../lib/jsdom/living/navigator")))
.done();
30 changes: 0 additions & 30 deletions test/living-html/navigator.js

This file was deleted.

1 change: 0 additions & 1 deletion test/runner
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ var files = [
"living-html/inline-event-handlers.js",
"living-html/location.js",
"living-html/message-event.js",
"living-html/navigator.js",
"living-html/on-error.js",
"living-html/post-message.js",

Expand Down
4 changes: 4 additions & 0 deletions test/web-platform-tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ describe("Web Platform Tests", () => {
"html/browsers/history/the-location-interface/location_port.html",
"html/browsers/history/the-location-interface/location_protocol.html",
"html/browsers/history/the-location-interface/location_search.html",
"html/browsers/offline/browser-state/navigator_online_online.html",
"html/browsers/windows/browsing-context-first-created.xhtml",
"html/dom/dynamic-markup-insertion/document-writeln/document.writeln-02.html",
"html/dom/dynamic-markup-insertion/document-writeln/document.writeln-03.html",
Expand Down Expand Up @@ -159,6 +160,9 @@ describe("Web Platform Tests", () => {
"html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html",
// "html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html", // template content owner document semantics not yet implemented
"html/webappapis/atob/base64.html",
"html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html",
"html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-indexed.html",
"html/webappapis/system-state-and-capabilities/the-navigator-object/navigatorlanguage.html",
"html/webappapis/timers/evil-spec-example.html",

"dom/events/Event-constants.html",
Expand Down
4 changes: 2 additions & 2 deletions test/window/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ exports.tests = {
aGlobal={win:this};\
</script>\
<script>\
appVersion = aGlobal.win.navigator.appVersion\
appVersion = aGlobal.win.navigator.product\
</script>\
</head><body></body></html>').defaultView;

test.strictEqual(window.appVersion, process.version);
test.strictEqual(window.appVersion, "Gecko");
test.done();
},

Expand Down
2 changes: 0 additions & 2 deletions test/worker-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ self.onmessage = function (e) {
"living-html/message-event.js": require("../test/living-html/message-event.js"), // ok
"living-html/post-message.js": require("../test/living-html/post-message.js"), // ok
"living-html/on-error.js": require("../test/living-html/on-error.js"), // ok
"living-html/navigator.js": require("../test/living-html/navigator.js"), // ok
"misc/url.js": require("../test/misc/url.js"), // ok
"misc/xhr-file-urls.js": require("../test/misc/xhr-file-urls.js"), // 0; file I/O does not work in browsers
"misc/xhr-requires-server.js": require("../test/misc/xhr-requires-server.js"), // 0; could work if we figured
Expand Down Expand Up @@ -86,7 +85,6 @@ self.onmessage = function (e) {
"living-html/location.js",
"living-html/inline-event-handlers.js",
"living-html/message-event.js",
"living-html/navigator.js",
"living-html/on-error.js",
"living-html/post-message.js",

Expand Down

0 comments on commit 306805a

Please sign in to comment.