Opened 6 years ago

Closed 5 years ago

Last modified 5 years ago

#14591 closed feature (fixed)

parser auto-load widget modules

Reported by: bill Owned by: bill
Priority: high Milestone: 1.8
Component: Parser Version: 1.7.1
Keywords: Cc: neonstalwart, cjolif
Blocked by: Blocking:

Description

(split from #13778)

Make the parser auto-load any modules not already there. This assumes the data-dojo-type=MID syntax from #13778.

dojo.parser.parse() will return a Deferred to indicate when parsing is finished.

This will be somewhat complicated to implement. It's easy to pause after parse() has done it's scanning work, before it calls instantiate(), and wait for all the widgets to load. However, during the parsing stage the parser checks each widget's prototype for _noScript and stopParser flags. Not sure how to deal with that.

Attachments (15)

parser_improvements.patch (9.2 KB) - added by kitsonk 6 years ago.
Additional improvements to the parser
parser_resturcture.patch (11.5 KB) - added by kitsonk 6 years ago.
Fixing some defects with my previous patches
parser_getElementsByTagName.patch (12.2 KB) - added by bill 6 years ago.
alternate patch
parser_getElementByTagName_mod.patch (12.9 KB) - added by kitsonk 6 years ago.
Modifies patch to deal with .stopParser and template
parser_deferred.patch (15.3 KB) - added by kitsonk 6 years ago.
Initial attempt at returning Deferred for parser.parse()
parser_auto-require.patch (17.0 KB) - added by kitsonk 6 years ago.
First attempt at auto-require
parser_auto-require_mixins.patch (21.6 KB) - added by kitsonk 6 years ago.
Auto Require with Mixins Support
parser_auto-require.2.patch (24.8 KB) - added by kitsonk 6 years ago.
Latest Patch for Comments
parser_auto-require.3.patch (27.8 KB) - added by kitsonk 6 years ago.
Refactoring taking on feedback
parser_auto-require.4.patch (29.2 KB) - added by kitsonk 6 years ago.
Minor refactors to improve clarity of code
dojo_parser_auto-require.patch (32.9 KB) - added by kitsonk 6 years ago.
dijit_parser_auto-require.patch (8.1 KB) - added by kitsonk 6 years ago.
demos_parser_auto-require.patch (42.1 KB) - added by kitsonk 6 years ago.
dojo_auto-require.patch (16.7 KB) - added by kitsonk 5 years ago.
Comprehensive dojo patch for auto-require
dijit_auto-require.patch (6.7 KB) - added by kitsonk 5 years ago.
Comprehensive dijit patch for auto-require

Download all attachments as: .zip

Change History (54)

comment:1 Changed 6 years ago by bill

  • Type changed from defect to enhancement

comment:2 Changed 6 years ago by neonstalwart

  • Cc neonstalwart added

comment:3 Changed 6 years ago by bill

In [27661]:

Parser refactoring based on ideas/code from Kitson Kelly (CLA):

  • use dojo/has
  • split DOM traversal from parse() into a separate function named scan()
  • split instantiate() into public function instantiate(), taking a list of nodes, and private function _instantiate(), taking (relatively) new argument structure.
  • rename "args" to "options"


Refs #14591 !strict.

Changed 6 years ago by kitsonk

Additional improvements to the parser

comment:4 Changed 6 years ago by kitsonk

Additional parser refactoring:

  • Changes scan from a while(true) loop to a query
  • Separates the resolution of the constructor to a separate function in preparation for auto-require
  • Implements propagateSettings in order to support flags like stopParser

comment:5 follow-up: Changed 6 years ago by neonstalwart

have you profiled these changes? the parser is a performance critical piece of code.

i recall that query was intentionally avoided due to performance reasons. see #10402 and #12450 for reference.

also, i'm wondering if any efficiency has been lost by breaking out these separate pieces. if they hurt performance but are needed to support a feature then i think we should defer making the changes until we can have the feature as well - ie, if we're going to pay a cost in performance we should at least be getting something in return, not just preparing to get something in return.

comment:6 in reply to: ↑ 5 Changed 6 years ago by kitsonk

Replying to neonstalwart:

have you profiled these changes? the parser is a performance critical piece of code.

At a high level, yes, but I intend to get more specific on performance before we really go anywhere on this. I will attach my latest attempt which changes things a little bit more.

i recall that query was intentionally avoided due to performance reasons. see #10402 and #12450 for reference.

Thanks, I will take a look at these.

also, i'm wondering if any efficiency has been lost by breaking out these separate pieces. if they hurt performance but are needed to support a feature then i think we should defer making the changes until we can have the feature as well - ie, if we're going to pay a cost in performance we should at least be getting something in return, not just preparing to get something in return.

Yes, I agree, but my conversation with Bill was that I was going to build this up, taking baby steps into a discreet patch. "Behind the scenes" I had taken a first stab at a total rewrite of the parser, to get it API compatible with this one, but restructure it wholly and find out what I needed and not needed to do. That worked, although the parser was about 1% slower than the existing one.

I have found some surprised. Like for example, there is now no-parsing of <script> tags in the parse() or scan(). In fact all the logic that was in there was in fact fully replicated, more efficiently in the instantiate(). Now it was generally short circuited, but my latest attempt has scan() as about as minimalistic as possible.

The discreet parts don't seem to impact performance, specifically, at least negligible. The way stopParser and the inheritance of lang, dir and data-dojo-textdir do impact performance, but I think I will be able to demonstrate it is immaterial. The thing I do argue though is that it will be challenging to do some things with the parser in the future unless there are discreet parts.

comment:7 Changed 6 years ago by kitsonk

For information, parser/bench.html is reporting on Chrome for the above patch:

AVERAGE TRIAL EXECUTION TIME: 148.5500000000ms.

And for current trunk:

AVERAGE TRIAL EXECUTION TIME: 169.0500000000ms.

So, if anything right at the moment, I am going the other direction.

comment:8 Changed 6 years ago by neonstalwart

fyi - results from IE are more critical than chrome

comment:9 Changed 6 years ago by kitsonk

Ok, the above patch works with IE6+ (except there is an extra attribute _zipIdx being created for some reason on IE6-8 and I will figure out what is going on with that).

Combined with Bill's new tests/parser/bench.html, here are the following numbers (on IE7) for the heavy DOM and heavy Widget with .stopParser:

  • Restructure: 147.95ms / 1852.90ms
  • Current Trunk: 165.75ms / 410.75ms
  • Pre-Breakout: 160.00 / 376.20ms

So I will do some thinking, especially with the heavy Widget with .stopParser.

Last edited 6 years ago by kitsonk (previous) (diff)

comment:10 Changed 6 years ago by kitsonk

Updated the patch with changes around how the inherited attributes are handled to try to work around some of the performance issues with IE. I have knocked a fair amount off the restructured with the widgets from where it was at, but I don't know if I could make it faster.

Restructure Current Trunk
DOM Scan.stopParserDOM Scan.stopParser
Chrome 16 182.05 127.55 173.25 163.55
Firefox 9 108.00 251.15 117.40 120.90
Safari 5 168.80 104.10 99.85 180.15
IE 9 95.70 394.70 101.60 239.80
IE 8 438.90 737.70 159.80 354.55
IE 7 443.40 842.90 158.40 404.40
IE Quirks 454.80 844.60 159.15 454.80

It is strange the significant behaviour difference between different browsers, in that some of the changes sped things up and in some cases it slowed them down. Most of the performance changes though except for IE were within sort of error rates really.

Changed 6 years ago by kitsonk

Fixing some defects with my previous patches

comment:11 Changed 6 years ago by kitsonk

Ok, I fixed a few things that were causing issues with my previous patch and the performance metrics of changed. Here is the latest stats under the restructure:

RestructureCurrent Trunk
DOM Scan.stopParserDOM Scan.stopParser
Chrome 16 93.80 125.85 181.05 104.50
Firefox 9 107.50 252.05 102.85 124.35
Safari 5 171.05 104.50 108.50 187.85
IE 9 122.60 144.10 75.75 87.90
IE 8 174.75 338.30 134.85 175.35
IE 7 172.50 403.80 135.70 218.70
IE Quirks 172.75 406.85 137.15 219.90

So I think the basic thing is that even with as many "tricks" as I can think of to short-circuit things, on IE, query isn't very efficient. What I might try tomorrow is to convert the scan loop back to a while(true) but preserving the new logic and see if that is more efficient on old IE. The thing I have been able to do though is almost eliminate in other browsers the overhead of inherited attributes.

Changed 6 years ago by bill

alternate patch

comment:12 Changed 6 years ago by bill

Yes, on IE, dojo.query() will always underperform a simple:

var nodes = root.getElementsByTagName("*"), idx = 0, node;
while(node = nodes[idx++]){
    if(node matches condition){ ...

I attached a patch that does such a loop, collecting the dojoType nodes and also corresponding <script type=dojo/*> nodes, and then resolves the inherited attributes (stopParser, lang, dir, and textdir) by tracing up the tree, but with caching of computed results for each node (regardless of whether or not the node has a dojoType).

It's working pretty well, on IE8 the results are:

current my patch your restructure
no widget scan 39 20 55
heavy widget scan 117 111 193
heavy widget scan w/stopParser 5 22 45

(Note that I checked in a fix to the test file, which previously wasn't really testing .stopParser.)

As expected, the scan time for when the page has just a few widgets (or no widgets) is improved, but the top-down scan outperforms query() or getElementsByTagName("*") when it can skip 90% of the DOM tree thanks to the stopParser flag.

Your _hasSpecialAttr flag is a nice trick to avoid overhead for the common case when there are no dir/lang/textdir parameters, and could possibly be used to improve my patch.

Last edited 6 years ago by bill (previous) (diff)

comment:13 Changed 6 years ago by kitsonk

Ok, I will work with the alternative patch and see what I can do. First quick note though, I forgot to mention in all of this, I noticed your TODO about verifying the selector in query. I played with all that yesterday, in my effort to mitigate the impact of using query, and I found some rather "shocking" things.

  • CSS2 - Slowed down modern browsers by about 10%
  • CSS2.1 - Slowed down modern and old browsers significantly (the "light" selector under-performed acme significantly in the attribute queries, by like a factor of 2
  • CSS3 - Slowed down modern browsers by about 10%

So, for the types of queries I was using yesterday it was best to leave it with acme, although we could be explicit in that so that people know we looked at it. I will check it, especially because I think even if we limit query in other ways, it is "the way" to do the declarative scripts now, since it just doesn't make sense to collect them during the scan.

comment:14 Changed 6 years ago by kitsonk

There was some changes that needed to be made to the patch that fixes issues with dijit/_WidgetsInTemplate and .stopParser, also some other minor modifications to get rid of some regressions (like dijit/Declaration). I think I caught them all, but in particular, the .stopParser performance changes (but very oddly between Chrome and IE for some reason). I am also explicit about which query selector we are using.

I also attempted to re-implement the _hasSpecialAttrs in this patch, but the overhead to figure that out significantly outweighed just doing it. It is overhead though that is just not needed for 99% of folks out there. I opened another feature request (#14691) to start to support the concept of overriding the type of parser being used, both through the options and the require parameters format. That way end developers will default to current situation, but anyone who wants to can just shut off the support for it.

Here is what I have from a performance perspective:

Chrome 16IE 9IE 7
DOMWidgetstopParserDOMWidgetstopParserDOMWidgetstopParser
_hasSpecialAttrs 179.35 113.25 149.90 130.85 111.65 107.95 169.70 278.25 107.30
Bill's "fixed" 155.10 109.40 199.75 124.05 110.85 70.85 86.15 278.90 79.80
Bill's 143.55 95.45 107.75 118.00 88.45 159.05 85.25 271.70 150.65
Trunk 172.55 162.45 127.95 75.10 86.15 156.65 134.90 217.05 99.05

I am going to try to figure out why "fixing" the .stopParser actually increases the performance on IE but slows down Chrome (and I think Firefox suffers from this too). Also, I will look at the bench tests to see if there are some good tests to add in there.

I will also look further into any benefits that can be driven out from using a different query selector.

But based on all of this, I am going to move forward with the assumption that generally speaking, we have "tread water" on the parser restructure, with some benefits in some browsers and negatives in others, but not significant and that I will attempt to do the "auto-require" based on the "Bill's 'fixed'" concepts.

Last edited 6 years ago by kitsonk (previous) (diff)

Changed 6 years ago by kitsonk

Modifies patch to deal with .stopParser and template

comment:15 follow-up: Changed 6 years ago by bill

Thanks for the fixes. A few notes:

Performance numbers: I think you are looking at the trial execution time rather than the test execution time, hence the numbers are meaningless. You should be looking at the test execution time; the trial time is some multiple of the test time, and the multiple will vary by browser. Also, are you really testing on IE7 or is that IE9 in IE7 compat mode? And in IE9, is the document mode set to IE9? It tends to go to IE7-compat mode on company intranets.

When I run the tests I get:

Chrome 16IE 9IE 7
DOMWidgetstopParserDOMWidgetstopParserDOMWidgetstopParser
Trunk 1.175 6.25 0.29 13.6 25.6 1.6 56.2 490.8 8.6
Bill's "fixed" 2.35 6.3 0.98 10.8 18.6 4.7 34.4 487.6 40.8

Regarding the query engine, there's a code-size/speed tradeoff between the lite engine and the acme engine, and the idea is that core code should specify the smallest engine possible (in this case apparently dojo/query!css2), and if the application wants to load the extra acme code, it can, by putting dojo/query!acme into it's require list. Haven't tried it myself but Kris tells me that the query engine will automatically use the acme code if it's loaded. Currently the query engine isn't being used much anyway, just for instantiate().

Regarding collecting <script type="dojo/*"> nodes, we need to consider performance first and foremost. My fear with doing it in instantiate() is that it will degrade performance by essentially scanning the DOM twice (once in scan() and once in _instantiate()). But we can benchmark it.

comment:16 in reply to: ↑ 15 Changed 6 years ago by kitsonk

Replying to bill:

Thanks for the fixes. A few notes:

Performance numbers: I think you are looking at the trial execution time rather than the test execution time, hence the numbers are meaningless. You should be looking at the test execution time; the trial time is some multiple of the test time, and the multiple will vary by browser. Also, are you really testing on IE7 or is that IE9 in IE7 compat mode? And in IE9, is the document mode set to IE9? It tends to go to IE7-compat mode on company intranets.

Ah yes, I see that now. My "AVERAGE TEST ITERATION TIME" are similar to yours. My "IE9" document mode is set to IE9 and "IE7" is IE9 in IE7. I will try to get a VM running with IE7 and/or IE8 so it is apples to apples.

Regarding the query engine, there's a code-size/speed tradeoff between the lite engine and the acme engine, and the idea is that core code should specify the smallest engine possible (in this case apparently dojo/query!css2), and if the application wants to load the extra acme code, it can, by putting dojo/query!acme into it's require list. Haven't tried it myself but Kris tells me that the query engine will automatically use the acme code if it's loaded. Currently the query engine isn't being used much anyway, just for instantiate().

Yes, it is less material now, but I will try to find the "optimum" setting. "css2.1" uses native or the light from what the documentation says and "css2" uses native or acme and "css3" uses native and nothing defaults to "acme" no matter what. And I certainly saw the differences in the performance yesterday (even though I was looking at the wrong number). So I will ferret out the right one, but you are right, it will be modest impact because it is barely used.

Regarding collecting <script type="dojo/*"> nodes, we need to consider performance first and foremost. My fear with doing it in instantiate() is that it will degrade performance by essentially scanning the DOM twice (once in scan() and once in _instantiate()). But we can benchmark it.

Yes, I agree now... the way scripts are being collected in the your patch's scan is effective. No need to change that.

comment:17 Changed 6 years ago by kitsonk

Ok, attached is a patch the builds on top of Bill's "fixed" and add initial support for the concept of Deferred return for the parser. If we agree with the concept for this potential patch, then I will fully move all of the separate parts of parser into a Deferred chain. I also realised that this will likely break a whole lot of stuff in pre-2.0 unless we add support for it as an option. So the format would look something like this:

require(["dojo/parser"], function(parser) {
  parser.parse({async:true}).then(function(objects){
    console.log("Parse Completed, now do something...");
  });
  
  console.log("Parser might not have completed, so don't do anything here...");
});

The patch also contains an update to the parser unit test to test this functionality. Also, it actually isn't async yet, as the Deferred is raised and resolved in the same code, but it paves the way for the async require needed for auto-require.

Last edited 6 years ago by kitsonk (previous) (diff)

Changed 6 years ago by kitsonk

Initial attempt at returning Deferred for parser.parse()

comment:18 Changed 6 years ago by cjolif

  • Cc cjolif added

Changed 6 years ago by kitsonk

First attempt at auto-require

comment:19 Changed 6 years ago by kitsonk

I have made an attempt at adding the auto-require functionality (also modified the unit tests to demonstrate). It seems to work with the exception of not having ContentPane already loaded before the parse. I need to look into that, but the code likely needs a bit of peer review. It is getting a bit far away from the trunk (which is what the patch is against) and it is hard to see the forest for the trees, so here is the snip of the code that is important:

if (_async){
  var mapCtorDeferred = new Deferred(),
    mids = [],
    missingObjs = []; 
  while(obj = objects[idx++]){
    try {
      obj.ctor = getCtor(obj.type);
      obj.proto = obj.ctor && obj.ctor.prototype;
    }catch(e){
      // If a module is not found, put in array to attempt to load
      mids.push(obj.type);
      missingObjs.push(obj);
    }
  }
  if (mids.length){
    // If there are missing modules, attempt to require them
    mids = unique(mids);
    require(mids, function(){
      while(obj = missingObjs[idx++]){
        // Trying to again, map the modules that were missing
        try {
          obj.ctor = getCtor(obj.type);
          obj.proto = obj.ctor && obj.ctor.prototype;
        }catch(e){}
      }
      // Now can resolve our deferred
      mapCtorDeferred.resolve(objects);
    });
  }else{
    // No modules missing, resolving deferred now
    mapCtorDeferred.resolve(objects);
  }
  // Returning deferred
  return mapCtorDeferred;
}

In the other ticket, we talked about potentially doing a RegExp on the MIDs to weed out anything that didn't look like a mid, but my particular feeling is that if we don't have to, why should we. What happens if a module gets passed that can't be loaded is you get a URL load failure from the loader.

As a side note, I suspect we are going to find some defects out there hiding away in code. I have a test page that has quite a diverse set of widgets which I used to have them all auto-require and something started complaining at "dijit.byId" was not a function and it wasn't anywhere in my code directly, so I suspect something isn't quite a baseless as it should be.

comment:20 Changed 6 years ago by bill

It seems like you could trim some bytes by require()'ing every module, regardless of whether or not it's already loaded. Require() can figure out which modules on the list need to be loaded. Of course you can't pass in legacy names like "dijit.form.Button" so you would need to filter those manually.

The other thing is that unique() is apparently running in n2 time, so it's probably worth using a hash to remove duplicates: every time a module is referenced set myHash[MID] = true, and then generate the unique list of MIDs by looping through the keys in myHash.

Also, looks like you aren't calling require() for MIDS specified in data-dojo-mixins?

As for the return value from parse(), my hope is to make it a combination of an array and Deferred, to maintain backwards compatibility while exposing the new API. So assuming that all modules are already loaded, users can do:

var list = dojo.parser.parse();
dojo.forEach(list, ...)

But also, regardless of async flags or what modules are loaded, users could do:

dojo.parser.parse().then(function(list){
    dojo.forEach(list, ...)
}

comment:21 Changed 6 years ago by kitsonk

Does anyone have any opinions on what the RegExp should be for checking MIDs?

For now, I am just excluding anything that has a .. Although that would exclude relative modules, although those shouldn't be used (as we discovered the loader will treat them as URIs). I think there will be challenges with Declaration.

if (/^[^\.]*$/.test(obj.type)){
  mids[obj.type] = true;
}

You are right about data-dojo-mixins. I need to look at that. It will likely have to be "broken out" from where it is at, so it can deal with the deferred.

comment:22 Changed 6 years ago by neonstalwart

The other thing is that unique() is apparently running in n2 time, so it's probably worth using a hash to remove duplicates: every time a module is referenced set myHash[MID] = true, and then generate the unique list of MIDs by looping through the keys in myHash.

avoid looping through the keys in the hash via something like this.

var seen = {};

return darray.filter(arr, function (item) {
    var duplicate = item in seen;
    seen[item] = 1;
    return !duplicate;
});

or even better, keep a hash of what's been added to mids and only add to mids if it hasn't been added already. this avoids looping over mids at all and you can remove unique completely.

var mids = [],
    seen = {};
while (obj = objects[idx++]) {
    ...
    catch (e) {
        if (!obj.type in seen) {
            seen[obj.type] = 1;
            mids.push(obj.type);
        ....
    }
}

comment:23 Changed 6 years ago by neonstalwart

i'd like to see if we can do this without all the try/catch blocks. it should be possible to sniff if something is a module id or an object reference. if it's a module id - we can unconditionally add it to mids without needing to call getCtor for it.

here's how i think the high level algorithm should be to avoid those try/catch blocks in the _async branch of the logic

  • iterate over objs and make an array of mids for EVERYTHING that looks like an mid (ie if it has a '/' in it, it's an mid).
  • require([mids] ...) and then inside the callback treat it exactly the same as in the sync case. in fact, probably have a private method for this (in the snippet below i called it _resolve) that gets called in both cases.
if (_async) {
    var dfd = new Deferred(),
        seen = {},
        type;
    while (obj = objects[idx++]) {
        type = obj.type;
        // if it looks like an mid and we haven't seen it already
        if (~type.indexOf('/') && !(type in seen)) {
            seen[type] = 1;
            mids.push(type);
        }
    }
    require(mids, function () {
        dfd.resolve(this._resolve(objs));
    });
    return dfd;
}
return this._resolve(objs);

comment:24 Changed 6 years ago by neonstalwart

...also in parse, use Deferred.when to avoid duplicating code

// this covers both async and sync cases without needing to check `_async`
return Deferred.when(this.mapCtorProto(list), function (list) {
    var mixin = options.template ? { template: true } : {};
    // if mapCtorProto was sync then this will be returned from parse
    return self._instantiate(self.propagateChildren(root, options, list), mixin, options);
});

Last edited 6 years ago by neonstalwart (previous) (diff)

comment:25 Changed 6 years ago by neonstalwart

sorry to keep following on like this...

you can also avoid _async by passsing options (or an async param) to mapCtorProto. to me, this seems better than relying on a shared _async variable in a containing scope. variables declared in the scope where you have _async declared would typically be used for things which apply on more than one run of the parser.

Changed 6 years ago by kitsonk

Auto Require with Mixins Support

Changed 6 years ago by kitsonk

Latest Patch for Comments

Changed 6 years ago by kitsonk

Refactoring taking on feedback

Changed 6 years ago by kitsonk

Minor refactors to improve clarity of code

Changed 6 years ago by kitsonk

Changed 6 years ago by kitsonk

Changed 6 years ago by kitsonk

Changed 5 years ago by kitsonk

Comprehensive dojo patch for auto-require

Changed 5 years ago by kitsonk

Comprehensive dijit patch for auto-require

comment:26 Changed 5 years ago by kitsonk

The two most recent patches provide dojo and dijit changes to enable the parser to auto-require.

comment:27 Changed 5 years ago by bill

In [28465]:

Modified version of Kitson's patch to support declarative require in the parser:

  1. Before looking for data-dojo-type nodes, the parser scans for <script type="dojo/require"> nodes, loads the specified modules, and then (asynchronously) continues the parse. If no <script type="dojo/require"> tags are present, parsing is synchronous like before.
  1. <script type="dojo/require"> syntax: hash mapping variable name to module id, ex: <script type="dojo/require"> baz: "acme/baz", zing: "acme/zing" </script>
  1. Parser return value: The parser's return value can be used as a Promise. In addition, for backwards compatibility, for markup without <script type=dojo/require> tags, the return value can be used as an array of widgets. (This code is common to #14591.)
  1. Corresponding changes to html.ContentSetter and dijit/layout/ContentPane to handle asynchronous parsing. These changes were taken from #14591 and tests will be added later when that ticket is closed.

Fixes #15118, refs #14591 !strict.

comment:28 Changed 5 years ago by bill

  • Milestone changed from future to 1.8
  • Type changed from enhancement to feature

comment:29 Changed 5 years ago by bill

  • Resolution set to fixed
  • Status changed from new to closed

In [28469]:

Modified version of Kitson's patch to support auto require in the parser.

Parser runs the same as before, unless scan() sees undefined modules, in which case it loads the modules asynchronously, and then runs patch-up code on list[], to fill in the missing constructors and remove any nodes that shouldn't be instantiated to due to a stopParser:true setting on an ancestor.

One API change is that scan() now returns a Promise. That's OK since scan() is new for 1.8.

Fixes #14591 !strict.

comment:30 Changed 5 years ago by bill

In [28482]:

Unit tests for parseOnLoad: true, also testing auto-require and declarative require, refs #14591, #15118 !strict.

comment:31 Changed 5 years ago by bill

In [28685]:

fix spacing etc., refs #14591 !strict.

comment:32 Changed 5 years ago by kitsonk

In [28824]:

refs #14591 #15118, demo for auto-require and declarative require features

comment:33 Changed 5 years ago by bill

In [29002]:

increase timeout to avoid spurious failure, refs #14591 !strict

comment:34 Changed 5 years ago by kitsonk

In [29127]:

Add warning about auto-require when isDebug=true, refs #14591 !strict

comment:35 Changed 5 years ago by bill

In [29324]:

Throw error in _WidgetsInTemplateMixin if parser does an async require (since async widget creation won't be supported until 2.0), refs #14591 !strict.

comment:36 Changed 5 years ago by bill

In [30523]:

since the parser will eventually only return a promise, start preparing for it now, refs #14591 !strict

comment:37 Changed 5 years ago by bill

In [30787]:

fix regression from [28465] where errors don't get reported, fixes #16813 and refs #15118, #14591 on 1.8/ branch, thanks Jared, !strict.

comment:38 Changed 5 years ago by bill

In [30788]:

fix regression from [28465] where errors don't get reported, fixes #16813 and refs #15118, #14591 on trunk/, thanks Jared, !strict.

comment:39 Changed 5 years ago by bill

In [30791]:

[30523] accidentally broke _earlyTemplatedStartup, put it back, refs #14591 !strict

Note: See TracTickets for help on using tickets.