#12672 closed enhancement (fixed)
enhance loader to be AMD-compliant while keeping dojo.provide/require backcompat
Reported by: | Rawld Gill | Owned by: | Rawld Gill |
---|---|---|---|
Priority: | high | Milestone: | 1.7 |
Component: | Loader | Version: | 1.6.0 |
Keywords: | loader bootstrap | Cc: | |
Blocked By: | Blocking: |
Description
This is a detailed description of the changes made to the v1.6- bootstrap and loader that move dojo to a fully AMD-capable and module system while maintaining backcompat with the dojo.provide/require module system.
Motivation and Goals
The purpose of this enhancement was to move from the dojo-proprietary loader API (dojo.provide
, dojo.require
et al) to the
CommonJS Modules/AsynchronousDefinition (AMD) API. This resulted
in the following benefits:
- Dojo modules are interoperable with other non-dojo-based systems
- Modules can be loaded asynchronously
- Owing to asynchronous loading, modules may be loaded by script injection; thereby improving the debugging environment
- Owing to asynchronous loading, many modules may be loaded concurrently, thereby improving loading performance
- Owing to asynchronous loading via script injection, there is no difference in loading algorithms when the modules reside "cross-domain", and therefore, the v1.6- synchronous and cross-domain loaders can be replaced by a single loader
- Owing to the AMD API, module namespaces can be sandboxed allowing several different versions of the same same module set or several different instances of the exact same module set to peacefully co-exist on a single web page. This capability of the AMD API completely eliminates the need for the so-called "multi-version" feature of dojo 1.6-.
Since the v1.6- bootstrap and loader are tightly integrated, it was impossible to replace the loader without
heavily modifying the bootstrap. Consequently, the bootstrap was completely refactored as part of this enhancement. Each
orthogonal feature set was divided into a separate module. This both decreased complexity and allowed for builds to
optionally discard unused features. For example, dojo._Url
and page unload detect are now optional features.
Coincident to this project, the has.js API was employed for feature detection as well as conditional code inclusion. In particular, the Dojo project is replacing build pragmas with has.js-bracketed code. This makes testing code branches easier and further decreases complexity by removing an extra-lingual construct (pragmas). The decision to add the has.js API as part of this project was made for the following reasons:
- the adopted asynchronous loader already included and required the has.js API
- the has.js API is part of the bootstrap which was already being heavily modified.
An overarching goal of this enhancement was to facilitate building optimized (in size) applications. As the mobile environment has become at least as important as the standard browser environment, optimizations for that environment are important. Where possible, features were added to enable optimizing for small, focused applications.
Finally, the enhancement maintains 100% backcompat with the 1.x dojo.provide/require API.
Overview of Changes
Broadly, the changes consequent to this enhancement included:
- Importing the bdLoad AMD loader into dojo and adding a backcompat API that supports synchronous operation and the dojo v1.6- loader API.
- Pulling the v1.6- bootstrap out of the 1.6- loader and reassembling it as a set of orthogonal modules.
- Removing any dependencies on private v1.6 loader features throughout the code stack since these features would not
exist with the new loader (e.g., some modules directly manipulated
dojo._loaders
, thedojo.addOnLoad
queue).
- Updating all the dojo unit tests to demonstrate the new system worked in both synchronous and asynchronous modes. dijit unit tests were intentionally left untouched to prove that "old code" would still work.
- Modifying all the module define applications in dojo and dijit to utilize anonymous module identifiers and relative module identifiers in define/require dependency vectors.
- Modifying DOH to be an AMD application to work with the browser, Rhino, and node.js.
- Providing a new build program that can consume the new AMD module format, the has.js API, and execute several new kinds of build transforms necessary to realize the potential of the the new module system and bootstrap refactor (e.g., provide a build for release that includes absolute module identifiers in place of the anonymous format found in the repository. The new build program operates on both node.js and rhino, and provides a platform going forward.
- Enhance the docscript program as required to consume the AMD module format.
Details of each of these items are discussed in separate sections below.
The Loader
bdLoad was donated by Altoviso LLC and imported into the dojo project.
The Bootstrap
The v1.6- sync-loader bootstrap evaluates the following modules (in the order given):
dojo.js
dojo/_base/_loader/bootstrap.js
dojo/_base/_loader/loader.js
dojo/_base/_loader/hostenv_browser.js
dojo/_base.js
Much of the non-loader functionality contained in the above modules has been moved to standard AMD modules as follows:
- The browser-only part of
dojo/_base.js
moved todojo/_base/browser.js
- Configuration processing found in
dojo.js
anddojo/_base/_loader/bootstrap.js
moved todojo.js
anddojo/_base/config.js
. It was necessary to duplicate the sniffing code in both the loader (dojo.js
) and the configuration module since we want to allow dojo to be loaded by foreign loaders. This duplication can be built out. - Non-browser configuration (e.g., node.js and rhino) have moved from
dojo/_base/_loader/hostenv_*.js
todojo/_base/config*.js
. Further, the bootstrap follows the philosophy, "assume the browser unless explicitly told otherwise." This is prudent since non-browser environments are on the local host, typically loaded via the file system, and a few extra bytes are inconsequential. - The most foundational dojo intialization, including defining the dojo object itself, found in
dojo/_base/_loader/bootstrap.js
moved todojo/_base/kernel.js
. - The
dojo.ready
(and the aliasdojo.addOnLoad
) moved todojo/_base/load.js
. - The v1.6- synchronous loader API (
dojo.provide
,dojo.require
et al) back compat layer is newly implemented indojo/_base/loader.js
anddojo.js
. This machinery is has-bracketed and may be easily built-out for AMD-only applications. - The browser version sniffing code found in
dojo/_base/_loader/hostenv_browser.js
moved todojo/_base/sniff.js
. dojo.getXhr
anddojo._getText
found indojo/_base/_loader/hostenv_browser.js
anddojo/_base/_loader/loader.js
respectively moved todojo.js
. Thedojo.getXhr
code is duplicated and has-bracketed indojo/_base/xhr.js
for cases when dojo is used with a foreign loader;dojo._getText
is not available with a foreign loader.dojo._Url
moved fromdojo/_base/_loader/_loader.js
todojo/_base/url.js
. It is currently unused in dojo; it may be easily replaced byrequire.nameToUrl
in dijit.dojo/_base.js
has been replaced bydojo/main.js
IAW CommonJS package conventions. It conditionally loadsdojo/_base/browser.js
depending upon the environment.
The bootstrap is fairly easy to understand. The so-called "base" modules depend on dojo/_base/kernel
which defines the
dojo object (the dojo *object* not the dojo *module*). The dojo module is defined by dojo/main.js
, and it depends on
all the base modules. Though there are some interdependencies, loosely speaking...
- dojo/main defines the module dojo and depends on...
- the dojo base modules, which populate the dojo object with the base API and depends on...
- dojo/kernel, which creates the dojo object, which depends on...
- dojo/config, which computes the configuration object, and dojo/has, which defines the has API; these modules depend on nothing.
All of this machinery can operate mostly the same with either dojo's native loader or a foreign loader. There are a few functions not available with a foreign loader.
Outline of Changes to the dojo Tree
The following modules are essentially rewritten:
dojo/dojo
new AMD loader with 1.x backcompat machinery.dojo/cache
empty now; implemented by the dojo/text plugin.dojo/text
the dojo/text plugin.dojo/i18n
the dojo/i18n plugin; all v1.6- i18n API is implemented through this module.dojo/has
the has.js API.dojo/main
the dojo package main module (essentially the old _base.js).dojo/_base/browser
dojo base modules for the browser environment.dojo/_base/config
all configuration sniffing/processing.dojo/_base/configNode
configuration for node.js.
dojo/_base/configRhino
configuration for rhino.js.dojo/_base/kernel
creates the dojo object.dojo/_base/load
the dojo.addOnLoad/ready API; this is now a priority queue.dojo/_base/loader
the dojo.provide/require et al API.dojo/_base/sniff
browser sniffing code (only) fromdojo/_base/_loader/_hostenvBrowser.js
.dojo/_base/unload
window unload API.dojo/_base/url
dojo._Url API.
The following modules have minor changes:
dojo/_base/array
removed native Javascript collection functions as per mailing list discussion.dojo/_base/declare
hasified IE enumeration bug; TODO: hasify shaman's rituals.dojo/_base/xhr
included has-bracketed xhr sniffing for use with foreign loaders.dojo/_base/lang
hasified IE enumeration bug.dojo/_firebug
moveddojo.deprecated
anddojo.experimental
out todojo/_base/kernel
.dojo/parser
used dojo.ready priority queue to remove dependency on dojo._loaders.dojo/uacss
used dojo.ready priority queue to remove dependency on dojo._loaders.dojo/package.json
added a few properties for the new builder.
All tests were modified to use define and require in place of dojo.provide and dojo.require so that they may be executed asynchronously. No changes were made to the actual tests contained within the test modules. The remaining dojo modules are not affected by this enhancement other that to remove the explicit module ids in the define statements, thereby making all modules anonymous.
Outline of Changes to the dijit Tree
- The explicit module ids were removed from all modules, thereby making all modules anonymous.
dijit/test/test_colorPalette
was modifed to operate either synchronously or asynchronously.dijit/themes/themetester.html
was slightly modified so it would work with anonymous modules.dijit/_base/wai
was modified to use the ready queue to removed the dependency on dojo._loaders.- The attempt to automatically create a savetextarea was deleted from
dijit/_editor/richText
as this code will not work reliably in async mode and has been problematic. The BackForward? test was modified by explicitly including a savetextarea. dijit/tests/_testCommon
was modified to use require.dojo/package.json
added a few properties for the new builder.
Outline of Changes to the dojox Tree
- A package main module was added.
Outline of Changes to the util Tree
- DOH was in need of some attention as it had been hacked on with many "quick fixes" and was becoming increasingly unreliable. It was generally cleaned up and turned into a proper set of AMD modules that form a small CommonJS package. DOH was enhanced to work with node.js; rhino operation was verified; self tests were added.
- The docscript was slighly modified to consume the AMD define function.
- A new build program was added. This will be tracked under a separate ticket.
Attachments (6)
Change History (229)
comment:1 Changed 10 years ago by
Owner: | set to Rawld Gill |
---|---|
Status: | new → assigned |
comment:2 Changed 10 years ago by
comment:3 Changed 10 years ago by
comment:4 Changed 10 years ago by
comment:5 follow-up: 8 Changed 10 years ago by
This change seems to have made doh dependent on dojo? It used to run standalone in rhino, and in the browser too IIRC. The doh/runner.sh no longer works as it passes runner.js directly into rhino, but presumably needs some wrapper to provide the AMD loader implementation before I can load that.
There were also other parameters for the rhino runner including testModule, dohBase. I can see why those are gone, but it breaks my proposed doh plugins patch in ticket:12625 (which is ok, I just need to rework it in the AMD world):
comment:6 follow-up: 9 Changed 10 years ago by
do you want bugs here or listed in separate tickets?
djConfig.modulePaths is not taken into consideration correctly (at all?). i can't figure out how to have trac accept script tags in my code blocks.
// first script tag djConfig = { modulePaths: {my: '/somewhere/else'} }; // script tag to load dojo // script tag to load app dojo.require('my.App'); // see console output below
loader/failed-sync *my/App ../dojo/my/App.js
comment:7 Changed 10 years ago by
comment:8 follow-up: 12 Changed 10 years ago by
Replying to sfoster:
This change seems to have made doh dependent on dojo? It used to run standalone in rhino, and in the browser too IIRC. The doh/runner.sh no longer works as it passes runner.js directly into rhino, but presumably needs some wrapper to provide the AMD loader implementation before I can load that.
There were also other parameters for the rhino runner including testModule, dohBase. I can see why those are gone, but it breaks my proposed doh plugins patch in ticket:12625 (which is ok, I just need to rework it in the AMD world):
Check out the README in util/doh which explains some of these issues.
util/doh/runner.sh was broken, but is now fixed (see #12625)
I made DOH dependent on dojo since, with AMD, dojo can be completely sandboxed, and therefore there is no reason to write/maintain duplicate code. This design decision can be tuned by including only specific dojo modules needed by DOH if necessary.
We should be able to easily enhance the patch in #12625 to use AMD module loading. That way there is one standardized way to extend a program and thereby eliminate machinery that duplicates function. I will help with #12625 going forward.
comment:9 Changed 10 years ago by
Replying to neonstalwart:
do you want bugs here or listed in separate tickets?
djConfig.modulePaths is not taken into consideration correctly (at all?). i can't figure out how to have trac accept script tags in my code blocks.
// first script tag djConfig = { modulePaths: {my: '/somewhere/else'} }; // script tag to load dojo // script tag to load app dojo.require('my.App'); // see console output belowloader/failed-sync *my/App ../dojo/my/App.js
The modulePaths backcompat machinery was not properly moved forward from 1.6. This is a bug I will repair. Thanks for the find.
comment:10 follow-up: 11 Changed 10 years ago by
comment:11 Changed 10 years ago by
comment:12 Changed 10 years ago by
Replying to rcgill:
Replying to sfoster:
This change seems to have made doh dependent on dojo? It used to run standalone in rhino, and in the browser too IIRC. The doh/runner.sh no longer works as it passes runner.js directly into rhino, but presumably needs some wrapper to provide the AMD loader implementation before I can load that.
There were also other parameters for the rhino runner including testModule, dohBase. I can see why those are gone, but it breaks my proposed doh plugins patch in ticket:12625 (which is ok, I just need to rework it in the AMD world):
Check out the README in util/doh which explains some of these issues.
util/doh/runner.sh was broken, but is now fixed (see #12625)
I made DOH dependent on dojo since, with AMD, dojo can be completely sandboxed, and therefore there is no reason to write/maintain duplicate code. This design decision can be tuned by including only specific dojo modules needed by DOH if necessary.
We should be able to easily enhance the patch in #12625 to use AMD module loading. That way there is one standardized way to extend a program and thereby eliminate machinery that duplicates function. I will help with #12625 going forward.
Change 1: util/doh/runner.sh is fixed in #12678
comment:15 Changed 10 years ago by
comment:16 Changed 10 years ago by
comment:17 Changed 10 years ago by
comment:19 Changed 10 years ago by
comment:21 Changed 10 years ago by
comment:22 Changed 10 years ago by
comment:24 Changed 10 years ago by
comment:25 follow-up: 65 Changed 10 years ago by
req.ready
does not account for the following signature:
dojo.ready(this, function () { ... });
it assumes that this
is a function that needs to be called because it only detects that it should be a context if the callback is a string.
comment:26 Changed 10 years ago by
comment:32 Changed 10 years ago by
comment:33 Changed 10 years ago by
comment:35 Changed 10 years ago by
I'm getting serious problems running the regression on webkit (specifically on chrome). the dijit/tests/runTests.html doesn't run at all, plus I get (the same?) failure in dojo/tests/html/test_set.html.
Probably something with firebug lite.
comment:36 Changed 10 years ago by
comment:38 Changed 10 years ago by
comment:39 Changed 10 years ago by
comment:40 Changed 10 years ago by
comment:41 Changed 10 years ago by
comment:42 Changed 10 years ago by
comment:43 Changed 10 years ago by
comment:44 Changed 10 years ago by
comment:45 Changed 10 years ago by
comment:46 Changed 10 years ago by
comment:47 Changed 10 years ago by
comment:48 Changed 10 years ago by
Recent changes have apparently broken the loader tests on IE9, running dojo/tests/runTests.html just gets the "unable to get property isDebug" error on all the initial (_base/loader) tests.
comment:49 Changed 10 years ago by
Also, the tests don't load at all unless you first hit F12 [and open the console tab]. Not sure if that's related to your checkin or not.
comment:50 Changed 10 years ago by
comment:51 Changed 10 years ago by
comment:52 follow-up: 66 Changed 10 years ago by
seems there is a regression in the way dojo.require() behaves. dojo.require has always assumed ../namespace for a modulePath (sibling of dojo/ tree) not explicitly defined in a dojoconfig.modulePaths obj. attached is a sample tree illustrating this issue.
<script src="../dojo/dojo.js"></script> <script>dojo.require("siblingns.test")</script>
should attempt to load ../siblingns/test.js
(relative to dojo.js) but it is attempting to load {{../dojo/siblingns/test.js}}} resulting in an "Synchronous XHR failed" message from the loader.
comment:53 follow-up: 106 Changed 10 years ago by
package.json is not valid json. unfortunately, there can be no comments in the file and this string doesn't parse ".*\.js$"
comment:54 follow-ups: 55 56 67 Changed 10 years ago by
require.has
is non-standard (ie more non-standard than the rest of the AMD "standard") and if dojo is loaded by a loader that doesn't implement it then we don't work. if we depend on require
having has
should we automatically augment an existing require
if it doesn't have has
(along with any other feature we expect from require)? in other words, do we need to feature detect require
?
comment:55 Changed 10 years ago by
Replying to neonstalwart:
require.has
is non-standard (ie more non-standard than the rest of the AMD "standard") and if dojo is loaded by a loader that doesn't implement it then we don't work. if we depend onrequire
havinghas
should we automatically augment an existingrequire
if it doesn't havehas
(along with any other feature we expect from require)? in other words, do we need to feature detectrequire
?
...OR should we make has
independent of require
.
comment:56 follow-up: 68 Changed 10 years ago by
Replying to neonstalwart:
require.has
is non-standard (ie more non-standard than the rest of the AMD "standard") and if dojo is loaded by a loader that doesn't implement it then we don't work. if we depend onrequire
havinghas
should we automatically augment an existingrequire
if it doesn't havehas
(along with any other feature we expect from require)? in other words, do we need to feature detectrequire
?
fyi - the point of failure is in dojo/has.js
var has = require.has; if(!has("loader-hasApi") && typeof has=="function"){ // notice the condition is written so that if has("loader-hasApi") is transformed to 1 during a build // the conditional will be (!1 && typeof has=="function") which is statically false and the closure // compiler will discard the block.
calling has
and then testing to see if it is a function seems like a logic error but the comments seem to suggest that this is intentional?
comment:57 follow-up: 75 Changed 10 years ago by
exports not defined when passed to the factory of a module that has no dependencies.
define(function (require, exports, module) { console.log('require: ', require); console.log('exports: ', exports); console.log('module: ', module); });
should http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=24447#L761 use module.cjs.exports
rather than module.exports
?
comment:58 follow-up: 59 Changed 10 years ago by
if i have registered a path to a module called listen
via
require({ paths: { listen: "path/to/listen" } });
and then in the listen
module, i use a relative path for a dependency
define(['./aop'], function (aop) { ... });
then the path for aop that is calculated by getModuleInfo (http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=24447#L626) is listen/.././aop
which will compact to aop
which is not going to return the module i'm requesting.
comment:59 Changed 10 years ago by
Replying to neonstalwart:
then the path for aop that is calculated by getModuleInfo (http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=24447#L626) is
listen/.././aop
which will compact toaop
which is not going to return the module i'm requesting.
fwiw, it will try to return baseUrl/aop
(in case that wasn't clear).
comment:60 Changed 10 years ago by
comment:61 Changed 10 years ago by
comment:62 Changed 10 years ago by
comment:63 Changed 10 years ago by
comment:65 Changed 10 years ago by
Replying to neonstalwart:
req.ready
does not account for the following signature:dojo.ready(this, function () { ... });
Just checked and this seems to be working as of [24480].
comment:66 Changed 10 years ago by
comment:67 Changed 10 years ago by
Replying to neonstalwart:
require.has
is non-standard (ie more non-standard than the rest of the AMD "standard") and if dojo is loaded by a loader that doesn't implement it then we don't work. if we depend onrequire
havinghas
should we automatically augment an existingrequire
if it doesn't havehas
(along with any other feature we expect from require)? in other words, do we need to feature detectrequire
?
The module dojo/has implements the has API when dojo is being used with a foreign loader. I'm sure there will be some details to work out when I/we test dojo with another loader, but there is nothing in the design intended to lock dojo into our own loader.
See also http://livedocs.dojotoolkit.org/developer/design/bootstrap
comment:68 Changed 10 years ago by
Replying to neonstalwart:
Replying to neonstalwart:
require.has
is non-standard (ie more non-standard than the rest of the AMD "standard") and if dojo is loaded by a loader that doesn't implement it then we don't work. if we depend onrequire
havinghas
should we automatically augment an existingrequire
if it doesn't havehas
(along with any other feature we expect from require)? in other words, do we need to feature detectrequire
?fyi - the point of failure is in dojo/has.js
var has = require.has; if(!has("loader-hasApi") && typeof has=="function"){ // notice the condition is written so that if has("loader-hasApi") is transformed to 1 during a build // the conditional will be (!1 && typeof has=="function") which is statically false and the closure // compiler will discard the block.calling
has
and then testing to see if it is a function seems like a logic error but the comments seem to suggest that this is intentional?
Right...that was written late at night :)...it's been changed.
comment:69 follow-up: 72 Changed 10 years ago by
in configNode.js, eval
and injectUrl
both use process.compile which gives warnings about being deprecated. besides this, in my experience (ie, can't find a doc to confirm this), the url hint provided to process.compile (or require('vm').runInThisContext its alternative) needs to be an absolute url for breakpoints to work for remote debugging.
comment:70 follow-up: 71 Changed 10 years ago by
given the url of my page is at http://some.server.com/app/
, doing the following with requirejs gives the init
module found at http://some.server.com/absolute/path/init.js
but with dojo it tries http://some.server.com/app/init.js
require({ baseUrl: '/absolute/path', packages: [ { name: 'dojo', location: '/different/absolute/path/to/dojo', main: 'lib/main', lib: '.' } ] }, ['init', 'dojo'], function (init, dojo) { // ... });
i could see arguments for either way being right so i changed the 'init'
dependency to './init'
hoping that it would do the right thing but instead it tried to load http://some.server.com/app//absolute/path/init.js
(note that //
is in the actual output)
my preference would be to follow requirejs in this case but i'd live with a workable version that needed './init'
if it had to be like that.
comment:71 Changed 10 years ago by
requirejs doesn't cope with '.' as a dependency - https://github.com/jrburke/requirejs/blob/0.24.0/require.js#L1267 explicitly checks for './' or '../'
should we ask james to make a change or should we avoid using '.'?
personally, i like the trickiness of using the '.' but i feel like we will be more readable and more likely to avoid problems by explicitly using 'dojo', 'dijit' and 'dojox' instead.
comment:72 Changed 10 years ago by
Replying to neonstalwart:
in configNode.js,
eval
andinjectUrl
both use process.compile which gives warnings about being deprecated. besides this, in my experience (ie, can't find a doc to confirm this), the url hint provided to process.compile (or require('vm').runInThisContext its alternative) needs to be an absolute url for breakpoints to work for remote debugging.
You're right. The code was developed under node v0.2.6 and needs to be updated to the current node version.
comment:73 Changed 10 years ago by
comment:74 Changed 10 years ago by
comment:75 Changed 10 years ago by
Replying to neonstalwart:
exports not defined when passed to the factory of a module that has no dependencies.
define(function (require, exports, module) { console.log('require: ', require); console.log('exports: ', exports); console.log('module: ', module); });
fixed in 24498
comment:76 Changed 10 years ago by
comment:77 Changed 10 years ago by
As reported on dojo-interest, dojo/tests/back.html is broken. Not surprising since it loads back.js via a <script> tag, and calls dojo.back.init() before dojo.ready() fires. However, the problem is that dojo.back.init() needs to be called before the document finishes loading. So not sure how/if this can be repaired, besides telling users to put back.js into their build of dojo.js.
comment:78 Changed 10 years ago by
comment:79 Changed 10 years ago by
comment:80 Changed 10 years ago by
comment:81 Changed 10 years ago by
Hi,
I'm not sure it's related, but when I try to generate layers for my application with the latest build it fails with the following message:
error loading uri: /data/release/Wfp2/dojo/_base.js, exception: Error: Could not load 'dojo._base.lang'; last tried '/data/release/Wfp2/dojo/_base/lang.js'
However /data/release/Wfp2/dojo/_base/lang.js exists...
comment:82 Changed 10 years ago by
comment:83 Changed 10 years ago by
comment:84 Changed 10 years ago by
comment:85 Changed 10 years ago by
REGRESSION: Not handling non-AMD v1.6-style i18n modules properly. Looks like dojo/i18n line 125 gets xhr results, but they never end up getting put into a nls cache properly, resulting in downstream root=undefined problem in dojo/i18n line 84. Good test case is dojox/widget/tests/test_ColorPicker.html
comment:86 Changed 10 years ago by
comment:87 Changed 10 years ago by
comment:88 Changed 10 years ago by
comment:89 Changed 10 years ago by
comment:90 Changed 10 years ago by
There's still some issues remaining in i18n compat for AMD loader. Here's info and a testcase from one of our teams. Best regards, Chris
I tested todays trunk, it is better but not completely OK yet:
The dojo.locale does not seem to be initialized from the djConfig variable. I also tried dojoConfig and the djconfig attribute of the dojo.js script element, whatever I do dojo.locale is set to the default browser locale (en-us by default). The only way to change the locale is to change the browser's locale (e.g., using about:config and changing general.useragent.local in Firefox).
Even after changing the browser's locale, the localized nls files are not loaded: the root (en-us) messages are loaded instead.
I am attaching the test that I use (to be extracted in the same directory as dojo/dijit/dojox). When run in a en-us browser, it will fail because the dojo.locale is not set according to the djConfig setting. If the browser's locale is changed to "fr", the test will fail because the loaded bundles do not match the locale.
The test passes OK on dojo 1.6, and also on the dojo 1.7 trunk versions prior to 4/1/2011.
Changed 10 years ago by
Attachment: | testI18N.zip added |
---|
comment:91 Changed 10 years ago by
comment:92 Changed 10 years ago by
comment:93 Changed 10 years ago by
comment:94 follow-up: 95 Changed 10 years ago by
it looks like some of this block http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=24651#L435 could be merged with the next block - they have the same if condition and they both get all the scripts and iterate over them. also, i'm confused as to why there is a check for require.js - this was really how i came to be looking at this code. will dojo support the data-main property like require.js?
comment:95 Changed 10 years ago by
Replying to neonstalwart:
it looks like some of this block http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=24651#L435 could be merged with the next block - they have the same if condition and they both get all the scripts and iterate over them. also, i'm confused as to why there is a check for require.js - this was really how i came to be looking at this code. will dojo support the data-main property like require.js?
I've debated this block myself. My idea was that I wanted dojo.js to be a drop-in replacement for RequireJS. The only thing you'd have to do is either rename dojo.js or have your server alias require.js to dojo.js. I don't feel strongly about this concept and welcome more feedback.
Seems that if we keep it, then it should be bracketed by a different has feature name...if it costs 1 byte in a built version that doesn't want it, then I definitely will cut it.
comment:96 Changed 10 years ago by
comment:97 follow-up: 98 Changed 10 years ago by
comment:98 follow-up: 99 Changed 10 years ago by
Replying to liucougar:
(In [24713]) refs #12672: timeout should be set to a number if missing, otherwise it won't be passed to _registerUrl() by register()
this broke backward compatibility
!strict
Did you see this change cause a different behavior? Because if you look at the implementation of
_registerUrl()
in _browserRunner.js you'll see
timeout: timeout||10000, // 10s
Let me know because I'm about to replace doh.register with an enhanced version and I think that will lose this change.
Thanks!
comment:99 Changed 10 years ago by
Replying to rcgill:
Did you see this change cause a different behavior? Because if you look at the implementation of
yes, it makes all of our tests which does not specify a timeout explicitly not registered at all. the problem is in function doh.register of file runner.js:
if(arity==3){ if(isNumber(a3)){ // (group, url, timeout) this._registerUrl(a1, a2, a3); }else if(isType(a3)){ ... } return; }
if a3 is not a number, _registerUrl is never called
comment:100 follow-up: 111 Changed 10 years ago by
is it safe to disregard the
end v1.x content
comment blocks in i18n files for 1.7? Adam mentioned that these were used in the 1.6 loader.
comment:101 Changed 10 years ago by
comment:102 Changed 10 years ago by
comment:103 Changed 10 years ago by
comment:104 Changed 10 years ago by
comment:105 Changed 10 years ago by
comment:107 Changed 10 years ago by
comment:108 Changed 10 years ago by
comment:109 Changed 10 years ago by
comment:110 Changed 10 years ago by
comment:111 Changed 10 years ago by
Replying to chrism:
is it safe to disregard the
end v1.x content
comment blocks in i18n files for 1.7? Adam mentioned that these were used in the 1.6 loader.
Yes, these are not required (but not harmful) in 1.7.
comment:112 Changed 10 years ago by
comment:114 Changed 10 years ago by
comment:115 Changed 10 years ago by
comment:116 Changed 10 years ago by
comment:117 Changed 10 years ago by
comment:118 Changed 10 years ago by
comment:119 Changed 10 years ago by
comment:120 Changed 10 years ago by
comment:121 Changed 10 years ago by
comment:122 follow-up: 125 Changed 10 years ago by
Bill, does the text! change break internStrings option in the build, or is rawld already planning to make those changes?
comment:123 follow-up: 126 Changed 10 years ago by
also, should we be doing similar changes in dojox/* as we port them to amd?
comment:124 follow-up: 127 Changed 10 years ago by
also, should we be using dojo/text! or text! (for better compat with requirejs
comment:125 Changed 10 years ago by
Replying to chrism:
Bill, does the text! change break internStrings option in the build, or is rawld already planning to make those changes?
I've planned for this. The semantics of internStrings are slightly different in the new builder:
case 1: AMD module: whenever a module has a text! dependency, that dependency is aggregated with the module during the build (like a mini implied layer...possibly as part of an explicit layer)
case 2: dojo.provide/require module: the string is added to the dojo.cache application (which will still be there since the option doesn't exist to use the text! plugin)...as has been done in the past.
comment:126 Changed 10 years ago by
Replying to chrism:
also, should we be doing similar changes in dojox/* as we port them to amd?
It will work either way. It boils down to choosing between
"text!some/bundle/name" in the deps vector
compared to
dojo.cache("some.bundle", "name") where the string is used.
The text! technique eliminates the need for yet-another-regular-expression in the builder, which is nice.
comment:127 Changed 10 years ago by
Replying to chrism:
also, should we be using dojo/text! or text! (for better compat with requirejs
Either will work with requirejs. dojo's text plugin is better than requirejs's because it leverages dojo. Also you could map one to the other.
My preference is to use dojo/text because it explicitly says we want to leverage dojo, and if the user insists on using something else, then they are at least somewhat responsible for any consequences.
comment:128 Changed 10 years ago by
comment:129 Changed 10 years ago by
comment:130 Changed 10 years ago by
comment:131 Changed 10 years ago by
comment:132 Changed 10 years ago by
comment:133 Changed 10 years ago by
comment:134 Changed 10 years ago by
comment:137 Changed 10 years ago by
comment:138 follow-up: 161 Changed 10 years ago by
require({ baseUrl: '/abs/path/to/base' }, ['init'], function (init) { // ... });
tries to fetch 'init'
from '/abs/path/to/init'
but i think it should be 'abs/path/to/base/init'
adding a path mapping fixes it:
require({ baseUrl: '/abs/path/to/base', paths: { init: 'init' } }, ['init'], function (init) { // ... });
but i would have expected that this mapping wouldn't be necessary
comment:140 Changed 10 years ago by
Changed 10 years ago by
Attachment: | baseReturns.patch added |
---|
prospective patch to fix return types of dojo/_base modules
comment:143 follow-up: 160 Changed 10 years ago by
dojo/text
and dojo/i18n
can't be mapped to top-level module ids - eg text
and i18n
respectively. given that there will be pre-existing usage of text
and i18n
is there a way to support this mapping for the sake of compatibility with existing use cases?
Changed 10 years ago by
Attachment: | baseReturns.2.patch added |
---|
updated return values from dojo/_base modules
comment:144 Changed 10 years ago by
comment:145 Changed 10 years ago by
When I tried loading 1.6- modules from dojox while in async mode, the loading fails because the calling factory function gets executed before all the 1.6-'s dependencies are synchronously loaded. For example, if I have dojo's config with async:true and then have a module:
define(dojox.gantt.GanttChart?, function(Chart){
this is executed after dojox/gantt/GanttChart.js, but before any of GanttChart?.js's dependencies are loaded
});
Attached is my attempt at a patch. Can you check to make sure it looks OK?
Changed 10 years ago by
Attachment: | fix-sync-loading.diff added |
---|
comment:146 Changed 10 years ago by
comment:148 follow-up: 150 Changed 10 years ago by
comment:149 Changed 10 years ago by
comment:150 Changed 10 years ago by
comment:151 Changed 10 years ago by
comment:152 Changed 10 years ago by
Replying to neonstalwart:
Replying to rcgill:
(In [25000]) fixed bug in require.toUrl when name is a relative path with no reference module; refs #12672; !strict
this adds a bug where the text plugin tries to fetch files as
some/file.js.html
in some circumstances - working on a minimal test to demonstrate
test case:
define('test', function () { return {}; }); require(['dojo/text!test.html'], function (test) { console.log(test); });
it seems that if the name of the html file (without the extension) matches the id of a module that has already been defined then .js
is added to the url such that test.html
becomes test.js.html
comment:153 Changed 10 years ago by
nevermind... r25014 fixed it while i was making the test case - thanks kzyp
comment:154 follow-up: 159 Changed 10 years ago by
http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=25014#L1044 from r25014 tries to use dojo.getObject
but dojo
doesn't always exist.
comment:155 follow-up: 158 Changed 10 years ago by
require.eval
(used when dojo.config.async
is not true
) does not evaluate in the global scope. example:
an html file contains
require(['test'], function () { console.log(test); });
and test.js contains
var test = 'abc';
if you use async loading, test
is a global but if you use synchronous loading test
is not defined. the key to being able to see this is the use of var
in test.js - of course without it, test
will be global no matter what scope test.js is evaluated in.
comment:156 Changed 10 years ago by
comment:158 Changed 10 years ago by
Replying to neonstalwart:
require.eval
(used whendojo.config.async
is nottrue
) does not evaluate in the global scope. example: an html file containsrequire(['test'], function () { console.log(test); });and test.js contains
var test = 'abc';if you use async loading,
test
is a global but if you use synchronous loadingtest
is not defined. the key to being able to see this is the use ofvar
in test.js - of course without it,test
will be global no matter what scope test.js is evaluated in.
There's more to it. In fact, test won't be defined in ie and some other browsers because of the way eval is defined in *both* 1.6- and 1.7 (though 1.7 is much better).
So, this is expected behavior.
comment:159 Changed 10 years ago by
Replying to neonstalwart:
http://bugs.dojotoolkit.org/browser/dojo/trunk/dojo.js?rev=25014#L1044 from r25014 tries to use
dojo.getObject
butdojo
doesn't always exist.
transferred to #13018
comment:160 Changed 10 years ago by
Replying to neonstalwart:
dojo/text
anddojo/i18n
can't be mapped to top-level module ids - egtext
andi18n
respectively. given that there will be pre-existing usage oftext
andi18n
is there a way to support this mapping for the sake of compatibility with existing use cases?
transferred to #13019
comment:161 Changed 10 years ago by
Replying to neonstalwart:
require({ baseUrl: '/abs/path/to/base' }, ['init'], function (init) { // ... });tries to fetch
'init'
from'/abs/path/to/init'
but i think it should be'abs/path/to/base/init'
<snip>
transferred to #13020
comment:162 Changed 10 years ago by
Component: | General → Loader |
---|
comment:163 Changed 10 years ago by
comment:165 Changed 10 years ago by
comment:166 Changed 10 years ago by
comment:167 Changed 10 years ago by
comment:168 Changed 10 years ago by
comment:169 Changed 10 years ago by
closing out this enhancement for 1.7. Please use new tickets for further issues.
comment:170 Changed 10 years ago by
comment:171 Changed 10 years ago by
comment:172 Changed 10 years ago by
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
All problem reports on this ticket have either been resolved or moved to other tickets.
Please open a new ticket to report problems with the 1.7 loader.
You may ref this ticket when committing minor/tuning changes to the loader until v1.7 release.
(In [24328]) added AMD loader, refs #12672 \!strict