Skip to content

Commit 87fdfa8

Browse files
committed
refactor: turns out that the whole server interaction couldnt possibly work because it didnt take into account concurrent connections. so, lots of changes, good thing it was caught before release
1 parent e7ee1be commit 87fdfa8

File tree

9 files changed

+396
-714
lines changed

9 files changed

+396
-714
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,15 @@
3737
"merge-stream": "^0.1.7",
3838
"mocha": "^2.2.4",
3939
"promiz": "^1.0.3",
40+
"qs": "^2.4.1",
4041
"rewire": "^2.3.1",
4142
"rewire-webpack": "^1.0.0",
4243
"transform-loader": "^0.2.1",
4344
"webpack": "^1.8.4"
4445
},
4546
"dependencies": {
4647
"coffee-script": "^1.9.2",
47-
"cookie": "^0.1.2",
4848
"lodash": "^3.6.0",
49-
"qs": "^2.4.1",
5049
"routes": "^2.0.0",
5150
"rx-lite": "^2.5.2",
5251
"vdom-to-html": "^2.0.0",

src/cookies.coffee

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/render_to_string.coffee

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
_ = require 'lodash'
2+
Rx = require 'rx-lite'
3+
toHTML = require 'vdom-to-html'
4+
5+
z = require './z'
6+
StateFactory = require './state_factory'
7+
8+
Promise = if window?
9+
window.Promise
10+
else
11+
_promiz = 'promiz'
12+
require _promiz
13+
14+
module.exports = (tree) ->
15+
new Promise (resolve) ->
16+
# for unbinding
17+
allStates = []
18+
states = []
19+
disposables = []
20+
21+
listener = ->
22+
z._startRecordingStates()
23+
z tree
24+
states = z._getRecordedStates()
25+
allStates = allStates.concat states
26+
z._stopRecordingStates()
27+
_.map states, (state) ->
28+
unless state._isSubscribing()
29+
state._bind_subscriptions()
30+
disposables.push state.subscribe listener
31+
setTimeout ->
32+
finish()
33+
34+
finish = ->
35+
isDone = _.every states, (state) ->
36+
state._isFulfilled()
37+
38+
if isDone
39+
result = z tree
40+
_.map disposables, (disposable) -> disposable.dispose()
41+
_.map allStates, (state) -> state._unbind_subscriptions()
42+
resolve toHTML result
43+
44+
listener()

src/server.coffee

Lines changed: 55 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
_ = require 'lodash'
2-
toHTML = require 'vdom-to-html'
32

43
z = require './z'
54
render = require './render'
65
StateFactory = require './state_factory'
7-
cookies = require './cookies'
86
isSimpleClick = require './is_simple_click'
97
ev = require './ev'
108

11-
SERVER_TIMEOUT_MS = 250
12-
139
getCurrentPath = (mode) ->
1410
hash = window.location.hash.slice(1)
1511
pathname = window.location.pathname
@@ -31,16 +27,6 @@ setPath = (path, mode, isReplacement) ->
3127

3228
class Server
3329
constructor: ->
34-
@events = {}
35-
@$$root = null
36-
@mode = if window?.history?.pushState then 'pathname' else 'hash'
37-
@currentPath = null
38-
@isRedrawScheduled = false
39-
@animationRequestId = null
40-
@$root = null
41-
@status = null # server only
42-
@req = null # server only
43-
4430
# coffeelint: disable=missing_fat_arrows
4531
@Redirect = ({path}) ->
4632
@name = 'redirect'
@@ -50,106 +36,42 @@ class Server
5036
@Redirect.prototype = new Error()
5137
# coffeelint: enable=missing_fat_arrows
5238

53-
if window?
54-
StateFactory.onAnyUpdate =>
55-
if @$root
56-
@go @currentPath
57-
58-
# used for full-page rendering
59-
@globalRoot = document.getElementById 'zorium-root'
60-
61-
unless @globalRoot
62-
@globalRoot = document.createElement 'div'
63-
@globalRoot.id = 'zorium-root'
64-
document.body.appendChild @globalRoot
65-
66-
# some browsers erroneously call popstate on intial page load (iOS Safari)
67-
# We need to ignore that first event.
68-
# https://code.google.com/p/chromium/issues/detail?id=63040
69-
window.addEventListener 'popstate', (e) =>
70-
if @currentPath
71-
setTimeout @go
72-
73-
setStatus: (@status) =>
74-
if window?
75-
throw new Error 'z.server.setStatus() called client-side'
76-
null
77-
78-
setCookie: cookies.set
79-
getCookie: cookies.get
80-
81-
getReq: =>
82-
if window?
83-
throw new Error 'z.server.getReq() called client-side'
84-
@req
85-
86-
factoryToMiddleware: (factory) =>
87-
handleRenderError = (err, req, res, next) =>
88-
if err instanceof @Redirect
89-
return res.redirect err.path
90-
else
91-
return next err
92-
93-
setResCookies = (res, cookies) ->
94-
_.map cookies.getConstructors(), (config, key) ->
95-
res.cookie key, config.value, config.opts
96-
97-
(req, res, next) =>
98-
# Reset state between requests
99-
@setStatus 200
100-
@req = req
101-
cookies.reset()
102-
StateFactory.reset()
103-
hasResolved = false
104-
105-
StateFactory.onError (err) ->
106-
if _.isPlainObject err
107-
err = new Error JSON.stringify err
108-
next err
109-
110-
cookies.populate req.headers?.cookie
111-
112-
$root = factory()
113-
114-
# FIXME
115-
# timeout = setTimeout =>
116-
# @emit 'timeout', {req}
117-
# resolve()
118-
# , SERVER_TIMEOUT_MSgd
119-
120-
resolve = =>
121-
if hasResolved
122-
return
123-
hasResolved = true
124-
# FIXME
125-
# clearTimeout timeout
126-
try
127-
tree = z $root, {
128-
path: req.url
129-
}
130-
131-
setResCookies(res, cookies)
132-
res.status(@status).send '<!DOCTYPE html>' + toHTML tree
133-
catch err
134-
setResCookies(res, cookies)
135-
handleRenderError(err, req, res, next)
136-
137-
# Initialize tree, kicking off async fetches
138-
try
139-
z $root, {
140-
path: req.url
141-
}
39+
unless window?
40+
return
14241

143-
StateFactory.onNextAllSettlemenmt resolve
42+
@events = {}
43+
@$$root = null
44+
@mode = if window?.history?.pushState then 'pathname' else 'hash'
45+
@currentPath = null
46+
@isRedrawScheduled = false
47+
@animationRequestId = null
48+
@$root = null
14449

145-
catch err
146-
hasResolved = true
147-
setResCookies(res, cookies)
148-
handleRenderError(err, req, res, next)
50+
StateFactory.onAnyUpdate =>
51+
if @$root
52+
@go @currentPath
53+
54+
# used for full-page rendering
55+
@globalRoot = document.getElementById 'zorium-root'
56+
57+
unless @globalRoot
58+
@globalRoot = document.createElement 'div'
59+
@globalRoot.id = 'zorium-root'
60+
document.body.appendChild @globalRoot
61+
62+
# some browsers erroneously call popstate on intial page load (iOS Safari)
63+
# We need to ignore that first event.
64+
# https://code.google.com/p/chromium/issues/detail?id=63040
65+
window.addEventListener 'popstate', (e) =>
66+
if @currentPath
67+
setTimeout @go
68+
69+
config: ({mode, $root, $$root}) =>
70+
unless window?
71+
throw new Error 'config called server-side'
14972

150-
config: ({mode, factory, $$root}) =>
15173
@mode = mode or @mode
152-
@$root = factory?() or @$root
74+
@$root = $root or @$root
15375
@$$root = $$root or @$$root
15476

15577
link: (node) =>
@@ -165,23 +87,6 @@ class Server
16587

16688
return node
16789

168-
render: (props) =>
169-
try
170-
tree = z @$root, props
171-
catch err
172-
if err instanceof @Redirect
173-
return @go err.path
174-
else throw err
175-
176-
# Because the DOM doesn't let us directly manipulate top-level elements
177-
# We have to standardize a hack around it
178-
179-
$root = if @$$root is document \
180-
then @globalRoot \
181-
else @$$root
182-
183-
render $root, tree
184-
18590
go: (path) =>
18691
unless window?
18792
throw new Error 'z.server.go() called server-side'
@@ -200,18 +105,36 @@ class Server
200105
path: path
201106
}
202107

108+
renderOrRedirect = (props) =>
109+
try
110+
tree = z @$root, props
111+
catch err
112+
if err instanceof @Redirect
113+
return @go err.path
114+
else throw err
115+
116+
# Because the DOM doesn't let us directly manipulate top-level elements
117+
# We have to standardize a hack around it
118+
$root = if @$$root is document \
119+
then @globalRoot \
120+
else @$$root
121+
render $root, tree
122+
203123
if not isRedraw
204124
@currentPath = path
205125
setPath path, @mode, hasRouted
206126
@emit 'go', {path}
207-
@render(props)
127+
renderOrRedirect(props)
208128
else
209129
@isRedrawScheduled = true
210130
@animationRequestId = window.requestAnimationFrame =>
211131
@isRedrawScheduled = false
212-
@render(props)
132+
renderOrRedirect(props)
213133

214134
on: (name, fn) =>
135+
unless window?
136+
throw new Error 'z.server.on() called server-side'
137+
215138
(@events[name] = @events[name] or []).push(fn)
216139

217140
emit: (name) =>
@@ -220,6 +143,9 @@ class Server
220143
fn.apply null, args
221144

222145
off: (name, fn) =>
146+
unless window?
147+
throw new Error 'z.server.off() called server-side'
148+
223149
@events[name] = _.without(@events[name], fn)
224150

225151
server = new Server()
@@ -229,10 +155,5 @@ module.exports = {
229155
go: server.go
230156
link: server.link
231157
config: server.config
232-
setStatus: server.setStatus
233-
setCookie: server.setCookie
234-
getCookie: server.getCookie
235-
getReq: server.getReq
236-
factoryToMiddleware: server.factoryToMiddleware
237158
Redirect: server.Redirect
238159
}

0 commit comments

Comments
 (0)