Skip to content

Commit ede27ae

Browse files
committed
polyfill clearTimeout and setTimeout for server side rendering
1 parent 8bea8e1 commit ede27ae

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

lib/react/server_rendering/sprockets_renderer.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ class SprocketsRenderer < ExecJSRenderer
1212
# Reimplement console methods for replaying on the client
1313
CONSOLE_POLYFILL = File.read(File.join(File.dirname(__FILE__), "sprockets_renderer/console_polyfill.js"))
1414
CONSOLE_REPLAY = File.read(File.join(File.dirname(__FILE__), "sprockets_renderer/console_replay.js"))
15+
TIMEOUT_POLYFILL = File.read(File.join(File.dirname(__FILE__), "sprockets_renderer/timeout_polyfill.js"))
1516

1617
def initialize(options={})
1718
@replay_console = options.fetch(:replay_console, true)
1819
filenames = options.fetch(:files, ["react-server.js", "components.js"])
1920
js_code = CONSOLE_POLYFILL.dup
21+
js_code << TIMEOUT_POLYFILL.dup
2022
js_code << options.fetch(:code, '')
2123

2224
filenames.each do |filename|
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
function getStackTrace() {
2+
var stack;
3+
try {
4+
throw new Error('');
5+
}
6+
catch (error) {
7+
stack = error.stack || '';
8+
}
9+
stack = stack.split('\\n').map(function (line) {
10+
return line.trim();
11+
});
12+
return stack.splice(stack[0] == 'Error' ? 2 : 1);
13+
};
14+
15+
function printError(functionName){
16+
console.error(functionName + ' is not defined for execJS. See https://github.com/sstephenson/execjs#faq. Note babel-polyfill may call this.');
17+
console.error(getStackTrace().join('\\n'));
18+
};
19+
20+
function setTimeout() {
21+
printError('setTimeout');
22+
};
23+
24+
function clearTimeout() {
25+
printError('clearTimeout');
26+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
WithSetTimeout = React.createClass({
2+
componentWillMount: function () {
3+
setTimeout(function () {}, 1000)
4+
clearTimeout(0)
5+
},
6+
render: function () {
7+
return <span>I am rendered!</span>
8+
}
9+
})

test/react/server_rendering/sprockets_renderer_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ class SprocketsRendererTest < ActiveSupport::TestCase
4848
assert_match(/\n/, err.to_s, "it includes the multi-line backtrace")
4949
end
5050

51+
test '#render polyfills setTimeout and clearTimeout and warn about it' do
52+
result = @renderer.render("WithSetTimeout", {}, nil)
53+
54+
assert_match(/I am rendered!<\/span>/, result)
55+
56+
message = "is not defined for execJS. See https://github.com/sstephenson/execjs#faq. Note babel-polyfill may call this."
57+
assert_match(/console.error.apply\(console, \["clearTimeout #{message}"\]\);$/, result)
58+
assert_match(/console.error.apply\(console, \["setTimeout #{message}"\]\);$/, result)
59+
end
60+
5161
test '.new accepts additional code to add to the JS context' do
5262
additional_code = File.read(File.expand_path("../../../helper_files/WithoutSprockets.js", __FILE__))
5363

0 commit comments

Comments
 (0)