Skip to content

Commit bfd070b

Browse files
committed
Merge branch 'pr-138' into stack-1.0.2
fixes elm#138
2 parents c8252f7 + defe9cc commit bfd070b

File tree

1 file changed

+89
-18
lines changed

1 file changed

+89
-18
lines changed

src/Elm/Kernel/Browser.js

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,41 +98,112 @@ var _Browser_document = __Debugger_document || F4(function(impl, flagDecoder, de
9898
// ANIMATION
9999

100100

101-
var _Browser_cancelAnimationFrame =
102-
typeof cancelAnimationFrame !== 'undefined'
103-
? cancelAnimationFrame
104-
: function(id) { clearTimeout(id); };
101+
var _Browser_requestAnimationFrame_queue = {};
102+
var _Browser_inAnimationFrame = false;
103+
var _Browser_pendingAnimationFrame = false;
104+
var _Browser_requestAnimationFrame_id = 0;
105105

106-
var _Browser_requestAnimationFrame =
106+
function _Browser_cancelAnimationFrame(id)
107+
{
108+
delete _Browser_requestAnimationFrame_queue[id];
109+
}
110+
111+
function _Browser_requestAnimationFrame(callback)
112+
{
113+
var id = _Browser_requestAnimationFrame_id;
114+
_Browser_requestAnimationFrame_id++;
115+
_Browser_requestAnimationFrame_queue[id] = callback;
116+
if (!_Browser_pendingAnimationFrame)
117+
{
118+
_Browser_pendingAnimationFrame = true;
119+
_Browser_requestAnimationFrame_raw(function() {
120+
_Browser_pendingAnimationFrame = false;
121+
_Browser_inAnimationFrame = true;
122+
var maxId = _Browser_requestAnimationFrame_id;
123+
for (var id2 in _Browser_requestAnimationFrame_queue)
124+
{
125+
if (id2 >= maxId)
126+
{
127+
break;
128+
}
129+
var callback = _Browser_requestAnimationFrame_queue[id2];
130+
delete _Browser_requestAnimationFrame_queue[id2];
131+
callback();
132+
}
133+
_Browser_inAnimationFrame = false;
134+
});
135+
}
136+
return id;
137+
}
138+
139+
var _Browser_requestAnimationFrame_raw =
107140
typeof requestAnimationFrame !== 'undefined'
108141
? requestAnimationFrame
109142
: function(callback) { return setTimeout(callback, 1000 / 60); };
110143

111-
112144
function _Browser_makeAnimator(model, draw)
113145
{
114-
draw(model);
146+
// Whether `draw` is currently running. `draw` can cause side effects:
147+
// If the user renders a custom element, they can dispatch an event in
148+
// its `connectedCallback`, which happens synchronously. That causes
149+
// `update` to run while we’re in the middle of drawing, which then
150+
// causes another call to the returned function below. We can’t start
151+
// another draw while before the first one is finished.
152+
var drawing = false;
115153

116-
var state = __4_NO_REQUEST;
154+
// Whether we have already requested an animation frame for drawing.
155+
var pendingFrame = false;
156+
157+
// Whether we have already requested to draw right after the current draw has finished.
158+
var pendingSync = false;
159+
160+
function drawHelp()
161+
{
162+
// If we’re already drawing, wait until that draw is done.
163+
if (drawing)
164+
{
165+
pendingSync = true;
166+
return;
167+
}
168+
169+
pendingFrame = false;
170+
pendingSync = false;
171+
drawing = true;
172+
draw(model);
173+
drawing = false;
174+
175+
if (pendingSync)
176+
{
177+
drawHelp();
178+
}
179+
}
117180

118181
function updateIfNeeded()
119182
{
120-
state = state === __4_EXTRA_REQUEST
121-
? __4_NO_REQUEST
122-
: ( _Browser_requestAnimationFrame(updateIfNeeded), draw(model), __4_EXTRA_REQUEST );
183+
if (pendingFrame)
184+
{
185+
drawHelp();
186+
}
123187
}
124188

189+
drawHelp();
190+
125191
return function(nextModel, isSync)
126192
{
127193
model = nextModel;
128194

129-
isSync
130-
? ( draw(model),
131-
state === __4_PENDING_REQUEST && (state = __4_EXTRA_REQUEST)
132-
)
133-
: ( state === __4_NO_REQUEST && _Browser_requestAnimationFrame(updateIfNeeded),
134-
state = __4_PENDING_REQUEST
135-
);
195+
// When using `Browser.Events.onAnimationFrame` we already are
196+
// in an animation frame, so draw straight away. Otherwise we’ll
197+
// be drawing one frame late all the time.
198+
if (isSync || _Browser_inAnimationFrame)
199+
{
200+
drawHelp();
201+
}
202+
else if (!pendingFrame)
203+
{
204+
pendingFrame = true;
205+
_Browser_requestAnimationFrame(updateIfNeeded);
206+
}
136207
};
137208
}
138209

0 commit comments

Comments
 (0)