So this is weird. Function.prototype.apply is supposed to be able to take an array of arguments and apply them to another function. (different from call where you have to specify the arguments separately.)
It looks to me like a function which was bound to an object (such as one wrapped by Language.closure) has the array passed into the first argument as an array instead of being passed in as a list of arguments. I have not seen this documented anywhere, but that’s what I’m seeing. Hmm. Actually, not sure about this. goog.bind is doing some weird stuff. Maybe that’s causing what I’m seeing? Why are we using goog.bind and not just the following in Language.closure? static public function closure(fn:Function, object:Object):Function { return function() { return fn.apply(object, arguments); }; } My understanding is that code will correctly bind the function call to this. It’s simpler, doesn’t require goog.bind and doesn’t require passing in function names. Am I missing something? Harbs > On Jan 5, 2022, at 9:37 AM, Harbs <harbs.li...@gmail.com> wrote: > > This function is a cool one. It lets you animate *anything*. You just specify > a target fps and run an arbitrary function and it’ll automatically be spaced > to execute at the target speed: > > The following will increment a value once every 50ms (1000/20fps) and run > exactly 30 times. > > var value:Number = 0; > function increment(val:Number):void{ > value+=val; > } > var animated:Function = animateFunction(increment,20); > var savedValue:Number; > for(i=0;i<30;i++){ > animated(1); > } > > Have fun! B-) > Harbs > >> On Jan 5, 2022, at 9:31 AM, ha...@apache.org wrote: >> >> This is an automated email from the ASF dual-hosted git repository. >> >> harbs pushed a commit to branch develop >> in repository https://gitbox.apache.org/repos/asf/royale-asjs.git >> >> >> The following commit(s) were added to refs/heads/develop by this push: >> new dd1c6e4 Added animateFunction >> dd1c6e4 is described below >> >> commit dd1c6e4cd7b082207a39efbf71de31adbb6de0d9 >> Author: Harbs <ha...@in-tools.com> >> AuthorDate: Wed Jan 5 09:31:10 2022 +0200 >> >> Added animateFunction >> --- >> .../projects/Core/src/main/royale/CoreClasses.as | 1 + >> .../royale/utils/functional/animateFunction.as | 130 >> +++++++++++++++++++++ >> .../src/test/royale/flexUnitTests/CoreTester.as | 2 +- >> .../test/royale/flexUnitTests/FunctionalTests.as | 34 ++++++ >> 4 files changed, 166 insertions(+), 1 deletion(-) >> >> diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as >> b/frameworks/projects/Core/src/main/royale/CoreClasses.as >> index 50c3c71..48189b5 100644 >> --- a/frameworks/projects/Core/src/main/royale/CoreClasses.as >> +++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as >> @@ -382,6 +382,7 @@ internal class CoreClasses >> import org.apache.royale.utils.functional.debounceLong; debounceLong; >> import org.apache.royale.utils.functional.debounceShort; debounceShort; >> import org.apache.royale.utils.functional.throttle; throttle; >> + import org.apache.royale.utils.functional.animateFunction; >> animateFunction; >> >> import org.apache.royale.core.TextLineMetrics; TextLineMetrics; >> import org.apache.royale.utils.ClassSelectorList; ClassSelectorList; >> diff --git >> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/functional/animateFunction.as >> >> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/functional/animateFunction.as >> new file mode 100644 >> index 0000000..32b9fbf >> --- /dev/null >> +++ >> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/functional/animateFunction.as >> @@ -0,0 +1,130 @@ >> +//////////////////////////////////////////////////////////////////////////////// >> +// >> +// Licensed to the Apache Software Foundation (ASF) under one or more >> +// contributor license agreements. See the NOTICE file distributed with >> +// this work for additional information regarding copyright ownership. >> +// The ASF licenses this file to You under the Apache License, Version 2.0 >> +// (the "License"); you may not use this file except in compliance with >> +// the License. You may obtain a copy of the License at >> +// >> +// http://www.apache.org/licenses/LICENSE-2.0 >> +// >> +// Unless required by applicable law or agreed to in writing, software >> +// distributed under the License is distributed on an "AS IS" BASIS, >> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >> +// See the License for the specific language governing permissions and >> +// limitations under the License. >> +// >> +//////////////////////////////////////////////////////////////////////////////// >> +package org.apache.royale.utils.functional >> +{ >> + COMPILE::SWF{ >> + import flash.utils.setTimeout; >> + import flash.utils.clearTimeout; >> + } >> + /** >> + * Returns a debounced function to run after a delay. >> + * The first invocation of the function will be run after its delay. >> + * Any invocations between the first invocation and the delay will be >> ignored. >> + * >> + * @royalesuppressexport >> + * @langversion 3.0 >> + * @productversion Royale 0.9.9 >> + * >> + */ >> + public function animateFunction(method:Function, fps:Number):Function >> + { >> + COMPILE::SWF >> + { >> + var limit:Number = 1000/fps; >> + var timeStamp:Number = 0; >> + var timeoutRef:*; >> + var invocations:Array = []; >> + return function(...args):void >> + { >> + if(timeoutRef){ >> + clearTimeout(timeoutRef); >> + timeoutRef = null; >> + } >> + invocations.push(args); >> + var currentTime:Number = new Date().getTime(); >> + var timeDiff:Number = currentTime - timeStamp; >> + if(timeDiff >= limit) >> + { >> + if(timeStamp == 0) >> + timeStamp = currentTime; >> + else >> + timeStamp += limit; >> + method.apply(null,invocations.shift()); >> + } >> + if(invocations.length && timeoutRef == null) >> + { >> + // currentTime = new Date().getTime(); >> + timeDiff = currentTime - timeStamp + >> limit; >> + var nextInterval:Number = >> Math.max(timeDiff,0); >> + timeoutRef = setTimeout(callback, >> nextInterval); >> + } >> + >> + function callback():void >> + { >> + timeoutRef = null; >> + >> + if(!invocations.length) >> + return; >> + >> + var currentArgs:Array = >> invocations.shift(); >> + method.apply(null,currentArgs); >> + timeStamp += limit; >> + var timeDiff:Number = new >> Date().getTime() - timeStamp + limit; >> + while(timeDiff < 0) >> + { >> + // catch up on the missing >> frames >> + >> method.apply(null,invocations.shift()); >> + if(invocations.length == 0) >> + { >> + return; >> + } >> + timeDiff+=limit; >> + } >> + if(invocations.length) >> + { >> + timeoutRef = >> setTimeout(callback, timeDiff); >> + } >> + } >> + } >> + >> + } >> + >> + COMPILE::JS >> + { >> + var limit:Number = 1000/fps; >> + var lastTimeStamp:Number = 0; >> + var timeoutRef:*; >> + var invocations:Array = []; >> + return function(...args):void >> + { >> + invocations.push(args); >> + requestAnimationFrame(callback); >> + function callback(timeStamp:Number):void >> + { >> + if(invocations.length == 0) >> + return; >> + >> + // we can't rely on getting time stamps >> ourselves, >> + // so hopefully this is not slower than >> our target rate... >> + if ( (timeStamp - lastTimeStamp) >= >> limit) >> + { >> + if(lastTimeStamp == 0) >> + lastTimeStamp = >> timeStamp; >> + else >> + lastTimeStamp += limit; >> // make sure we stick to the desired rate >> + >> + >> method.apply(null,invocations.shift()); >> + } >> + if(invocations.length) >> + requestAnimationFrame(callback); >> + } >> + } >> + } >> + } >> +} >> \ No newline at end of file >> diff --git >> a/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as >> b/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as >> index 7b15375..eeb4e76 100644 >> --- a/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as >> +++ b/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as >> @@ -45,7 +45,7 @@ package flexUnitTests >> public var sanitizerTest:SanitizeTest; >> public var eventsTest:EventsTest; >> public var objectUtilTests:ObjectUtilsTest; >> - public var functionelTests:FunctionalTests; >> + public var functionalTests:FunctionalTests; >> >> } >> } >> diff --git >> a/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as >> b/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as >> index 022c4da..75f320c 100644 >> --- >> a/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as >> +++ >> b/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as >> @@ -25,6 +25,8 @@ package flexUnitTests >> import org.apache.royale.test.asserts.*; >> import org.apache.royale.test.async.*; >> import org.apache.royale.utils.functional.*; >> + import org.apache.royale.utils.functional.animateFunction; >> + import org.apache.royale.test.asserts.assertTrue; >> >> public class FunctionalTests >> { >> @@ -192,6 +194,38 @@ package flexUnitTests >> assertEquals(value,7,"value should be 7"); >> }, 300); >> } >> + [Test(async,timeout="300")] >> + public function testAnimate():void >> + { >> + var foo:Foo = new Foo(); >> + var animateThis:Function = animateFunction(foo.increment,20); >> + for(var i:int=0;i<30;i++){ >> + animateThis(1); >> + } >> + var savedThisValue:Number; >> + setTimeout(function():void{ >> + savedThisValue = foo.value; >> + },50); >> + >> + var value:Number = 0; >> + function increment(val:Number):void{ >> + value+=val; >> + } >> + var animated:Function = animateFunction(increment,20); >> + var savedValue:Number; >> + for(i=0;i<30;i++){ >> + animated(1); >> + } >> + >> + setTimeout(function():void{ >> + savedValue = value; >> + },50); >> + Async.delayCall(this, function():void >> + { >> + assertTrue(savedThisValue<3,"foo value should be 2"); >> + assertTrue(savedValue<3,"value should be 2"); >> + }, 300); >> + } >> >> >> } >