Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Save a reference to the native Object object #31

Closed
wants to merge 2 commits into from

2 participants

@DavidBruant

I needed to use benchmark.js in an environment where I had overridden the Object built-in. The following change made the difference between benchmark.js not working (for unclear reasons) to working.

jdalton and others added some commits
@jdalton jdalton Update vendors. 2c1d5d4
@DavidBruant DavidBruant Save a reference to the native Object object
I needed to use benchmark.js in an environment where I had overridden the Object built-in.
866e435
@DavidBruant

Tried npm test and it fails indeed. Not really sure why.

/home/david/gitRepo/HarmonyProxyLab/benchmark.js/benchmark.js:31
  var getAllKeys = Object.getOwnPropertyNames;
                         ^
TypeError: Cannot read property 'getOwnPropertyNames' of undefined

My tests in browsers work fine.

@jdalton
Owner

No worries. Is there a public repo to see the Object replacement. I'm curious at the use case for that.

@DavidBruant

https://github.com/DavidBruant/HarmonyProxyLab/blob/ES3AndProxy/ES3AndProxy/ES5ObjectModelEmul.js
It is known that Object.defineProperty is slow in Firefox; likewise for getters/setters. I'm doing some experiment seeing if it's realistic to consider self-hosting the ES5 object model (property descriptors, [[Extensible]]) on top of proxies and objects-as-map (object which interface is reduced to get/set/has/delete with a [[Prototype]]).
I chose to create the custom objects with new Object() (which is why I needed to replace Object). I could have chosen otherwise, but nah...

I needed world-class quality benchmarks to see if what I had started with had a chance. I'm currently a bit faster than twice as fast, but I haven't fully implemented the algorithms, so I'm still unsure if it's going to work out. Thanks for benchmark.js :-)

Next step is injecting my Object replacement in Test262 tests as well as automatically rewriting them to generate my type of objects (in progress), then reaching full conformance in relevant tests.
Then, realize I'm slower, optimize the shit out of my implementation with the goal to reach something at least as fast to prove feasibility.

Test262 catches a good number of Firefox bugs with regard to property descriptors (Object.defineProperties and on arrays). If I happen to be faster with my self-hosted version, I'll have better conformance and better performance. Rings a bell? Yeah, you've been an inspiration ;-)

@jdalton jdalton closed this in 1cb8c21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 25, 2012
  1. @jdalton

    Update vendors.

    jdalton authored
Commits on Dec 8, 2012
  1. @DavidBruant

    Save a reference to the native Object object

    DavidBruant authored
    I needed to use benchmark.js in an environment where I had overridden the Object built-in.
This page is out of date. Refresh to see the latest.
View
3  benchmark.js
@@ -8,6 +8,9 @@
;(function(window, undefined) {
'use strict';
+ /** Save a copy of the Object built-in in case someone overrides it later */
+ var Object = window.Object;
+
/** Used to assign each benchmark an incrimented id */
var counter = 0;
View
14 vendor/qunit/README.md
@@ -1,4 +1,4 @@
-[QUnit](http://docs.jquery.com/QUnit) - A JavaScript Unit Testing framework.
+[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework.
================================
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
@@ -35,7 +35,8 @@ the change, run `grunt` to lint and test it, then commit, push and create a pull
Include some background for the change in the commit message and `Fixes #nnn`, referring
to the issue number you're addressing.
-To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`.
+To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global
+grunt binary. For additional grunt tasks, also run `npm install`.
Releases
--------
@@ -47,3 +48,12 @@ tag, update them again to the next version, commit and push commits and tags
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
or whitespace cleanups.
+
+To upload to code.jquery.com (replace $version accordingly):
+
+ scp -q qunit/qunit.js jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.js
+ scp -q qunit/qunit.css jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.css
+
+Then update /var/www/html/code.jquery.com/index.html and purge it with:
+
+ curl -s http://code.origin.jquery.com/?reload
View
16 vendor/qunit/qunit/qunit.css
@@ -1,11 +1,11 @@
/**
- * QUnit v1.9.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
- * http://docs.jquery.com/QUnit
+ * http://qunitjs.com
*
- * Copyright (c) 2012 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
*/
/** Font Family and Sizes */
@@ -20,7 +20,7 @@
/** Resets */
-#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
+#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
@@ -67,6 +67,7 @@
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
+ overflow: hidden;
}
#qunit-userAgent {
@@ -76,6 +77,9 @@
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
+#qunit-modulefilter-container {
+ float: right;
+}
/** Tests: Pass/Fail */
View
89 vendor/qunit/qunit/qunit.js
@@ -1,11 +1,11 @@
/**
- * QUnit v1.9.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
- * http://docs.jquery.com/QUnit
+ * http://qunitjs.com
*
- * Copyright (c) 2012 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
*/
(function( window ) {
@@ -17,6 +17,8 @@ var QUnit,
fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
+ // Keep a local reference to Date (GH-283)
+ Date = window.Date,
defined = {
setTimeout: typeof window.setTimeout !== "undefined",
sessionStorage: (function() {
@@ -304,7 +306,8 @@ QUnit = {
// call on start of module test to prepend name to all tests
module: function( name, testEnvironment ) {
config.currentModule = name;
- config.currentModuleTestEnviroment = testEnvironment;
+ config.currentModuleTestEnvironment = testEnvironment;
+ config.modules[name] = true;
},
asyncTest: function( testName, expected, callback ) {
@@ -336,7 +339,7 @@ QUnit = {
async: async,
callback: callback,
module: config.currentModule,
- moduleTestEnvironment: config.currentModuleTestEnviroment,
+ moduleTestEnvironment: config.currentModuleTestEnvironment,
stack: sourceFromStacktrace( 2 )
});
@@ -349,7 +352,11 @@ QUnit = {
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
expect: function( asserts ) {
- config.current.expected = asserts;
+ if (arguments.length === 1) {
+ config.current.expected = asserts;
+ } else {
+ return config.current.expected;
+ }
},
start: function( count ) {
@@ -415,6 +422,8 @@ QUnit.assert = {
var source,
details = {
+ module: config.current.module,
+ name: config.current.testName,
result: result,
message: msg
};
@@ -600,6 +609,9 @@ config = {
}
],
+ // Set of all modules.
+ modules: {},
+
// logging callback queues
begin: [],
done: [],
@@ -710,17 +722,10 @@ extend( QUnit, {
},
// Resets the test setup. Useful for tests that modify the DOM.
- // If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
reset: function() {
- var fixture;
-
- if ( window.jQuery ) {
- jQuery( "#qunit-fixture" ).html( config.fixture );
- } else {
- fixture = id( "qunit-fixture" );
- if ( fixture ) {
- fixture.innerHTML = config.fixture;
- }
+ var fixture = id( "qunit-fixture" );
+ if ( fixture ) {
+ fixture.innerHTML = config.fixture;
}
},
@@ -781,6 +786,8 @@ extend( QUnit, {
var output, source,
details = {
+ module: config.current.module,
+ name: config.current.testName,
result: result,
message: message,
actual: actual,
@@ -826,6 +833,8 @@ extend( QUnit, {
var output,
details = {
+ module: config.current.module,
+ name: config.current.testName,
result: false,
message: message
};
@@ -916,7 +925,9 @@ QUnit.load = function() {
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
- var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,
+ var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
+ numModules = 0,
+ moduleFilterHtml = "",
urlConfigHtml = "",
oldconfig = extend( {}, config );
@@ -940,6 +951,15 @@ QUnit.load = function() {
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
}
+ moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>";
+ for ( i in config.modules ) {
+ if ( config.modules.hasOwnProperty( i ) ) {
+ numModules += 1;
+ moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
+ }
+ }
+ moduleFilterHtml += "</select>";
+
// `userAgent` initialized at top of scope
userAgent = id( "qunit-userAgent" );
if ( userAgent ) {
@@ -1002,6 +1022,19 @@ QUnit.load = function() {
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigCheckboxes );
+
+ if (numModules > 1) {
+ moduleFilter = document.createElement( 'span' );
+ moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
+ moduleFilter.innerHTML = moduleFilterHtml;
+ addEvent( moduleFilter, "change", function() {
+ var selectBox = moduleFilter.getElementsByTagName("select")[0],
+ selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+
+ window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
+ });
+ toolbar.appendChild(moduleFilter);
+ }
}
// `main` initialized at top of scope
@@ -1039,9 +1072,9 @@ window.onerror = function ( error, filePath, linerNr ) {
}
QUnit.pushFailure( error, filePath + ":" + linerNr );
} else {
- QUnit.test( "global failure", function() {
+ QUnit.test( "global failure", extend( function() {
QUnit.pushFailure( error, filePath + ":" + linerNr );
- });
+ }, { validTest: validTest } ) );
}
return false;
}
@@ -1108,6 +1141,11 @@ function done() {
}
}
+ // scroll back to top to show results
+ if ( window.scrollTo ) {
+ window.scrollTo(0, 0);
+ }
+
runLoggingCallbacks( "done", QUnit, {
failed: config.stats.bad,
passed: passed,
@@ -1123,6 +1161,12 @@ function validTest( test ) {
module = config.module && config.module.toLowerCase(),
fullName = (test.module + ": " + test.testName).toLowerCase();
+ // Internally-generated tests are always valid
+ if ( test.callback && test.callback.validTest === validTest ) {
+ delete test.callback.validTest;
+ return true;
+ }
+
if ( config.testNumber ) {
return test.testNumber === config.testNumber;
}
@@ -1404,7 +1448,8 @@ QUnit.equiv = (function() {
a.global === b.global &&
// (gmi) ...
a.ignoreCase === b.ignoreCase &&
- a.multiline === b.multiline;
+ a.multiline === b.multiline &&
+ a.sticky === b.sticky;
},
// - skip when the property is a method of an instance (OOP)
View
91 vendor/requirejs/require.js
@@ -1,5 +1,5 @@
/** vim: et:ts=4:sw=4:sts=4
- * @license RequireJS 2.1.0 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
+ * @license RequireJS 2.1.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
@@ -12,7 +12,7 @@ var requirejs, require, define;
(function (global) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
- version = '2.1.0',
+ version = '2.1.1',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
@@ -100,9 +100,6 @@ var requirejs, require, define;
/**
* Simple function to mix in properties from source into target,
* but only if target does not already have a property of the same name.
- * This is not robust in IE for transferring methods that match
- * Object.prototype names, but the uses of mixin here seem unlikely to
- * trigger a problem related to that.
*/
function mixin(target, source, force, deepStringMixin) {
if (source) {
@@ -195,7 +192,9 @@ var requirejs, require, define;
baseUrl: './',
paths: {},
pkgs: {},
- shim: {}
+ shim: {},
+ map: {},
+ config: {}
},
registry = {},
undefEvents = {},
@@ -1167,6 +1166,25 @@ var requirejs, require, define;
};
}
+ function intakeDefines() {
+ var args;
+
+ //Any defined modules in the global queue, intake them now.
+ takeGlobalQueue();
+
+ //Make sure any remaining defQueue items get properly processed.
+ while (defQueue.length) {
+ args = defQueue.shift();
+ if (args[0] === null) {
+ return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
+ } else {
+ //args are id, deps, factory. Should be normalized by the
+ //define() function.
+ callGetModule(args);
+ }
+ }
+ }
+
context = {
config: config,
contextName: contextName,
@@ -1194,20 +1212,23 @@ var requirejs, require, define;
//they are additive.
var pkgs = config.pkgs,
shim = config.shim,
- paths = config.paths,
- map = config.map;
-
- //Mix in the config values, favoring the new values over
- //existing ones in context.config.
- mixin(config, cfg, true);
-
- //Merge paths.
- config.paths = mixin(paths, cfg.paths, true);
+ objs = {
+ paths: true,
+ config: true,
+ map: true
+ };
- //Merge map
- if (cfg.map) {
- config.map = mixin(map || {}, cfg.map, true, true);
- }
+ eachProp(cfg, function (value, prop) {
+ if (objs[prop]) {
+ if (prop === 'map') {
+ mixin(config[prop], value, true, true);
+ } else {
+ mixin(config[prop], value, true);
+ }
+ } else {
+ config[prop] = value;
+ }
+ });
//Merge shim
if (cfg.shim) {
@@ -1288,8 +1309,8 @@ var requirejs, require, define;
makeRequire: function (relMap, options) {
options = options || {};
- function require(deps, callback, errback) {
- var id, map, requireMod, args;
+ function localRequire(deps, callback, errback) {
+ var id, map, requireMod;
if (options.enableBuildCallback && callback && isFunction(callback)) {
callback.__requireJsBuild = true;
@@ -1328,23 +1349,15 @@ var requirejs, require, define;
return defined[id];
}
- //Any defined modules in the global queue, intake them now.
- takeGlobalQueue();
-
- //Make sure any remaining defQueue items get properly processed.
- while (defQueue.length) {
- args = defQueue.shift();
- if (args[0] === null) {
- return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
- } else {
- //args are id, deps, factory. Should be normalized by the
- //define() function.
- callGetModule(args);
- }
- }
+ //Grab defines waiting in the global queue.
+ intakeDefines();
//Mark all the dependencies as needing to be loaded.
context.nextTick(function () {
+ //Some defines could have been added since the
+ //require call, collect them.
+ intakeDefines();
+
requireMod = getModule(makeModuleMap(null, relMap));
//Store if map config should be applied to this require
@@ -1358,10 +1371,10 @@ var requirejs, require, define;
checkLoaded();
});
- return require;
+ return localRequire;
}
- mixin(require, {
+ mixin(localRequire, {
isBrowser: isBrowser,
/**
@@ -1394,7 +1407,7 @@ var requirejs, require, define;
//Only allow undef on top level require calls
if (!relMap) {
- require.undef = function (id) {
+ localRequire.undef = function (id) {
//Bind any waiting define() calls to this context,
//fix for #408
takeGlobalQueue();
@@ -1419,7 +1432,7 @@ var requirejs, require, define;
};
}
- return require;
+ return localRequire;
},
/**
Something went wrong with that request. Please try again.