Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
renderjs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
renderjs
Commits
0c2428ca
Commit
0c2428ca
authored
Oct 24, 2017
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Give a name to all anonymous functions.
This will make JS stack more readable.
parent
be096475
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
273 additions
and
279 deletions
+273
-279
renderjs.js
renderjs.js
+273
-279
No files found.
renderjs.js
View file @
0c2428ca
...
...
@@ -5,19 +5,20 @@
* renderJs - Generic Gadget library renderer.
* http://www.renderjs.org/documentation
*/
(
function
(
document
,
window
,
RSVP
,
DOMParser
,
Channel
,
MutationObserver
,
Node
,
FileReader
,
Blob
,
navigator
,
Event
,
URL
)
{
(
function
wrapRenderJS
(
document
,
window
,
RSVP
,
DOMParser
,
Channel
,
MutationObserver
,
Node
,
FileReader
,
Blob
,
navigator
,
Event
,
URL
)
{
"
use strict
"
;
function
readBlobAsDataURL
(
blob
)
{
var
fr
=
new
FileReader
();
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
fr
.
addEventListener
(
"
load
"
,
function
(
evt
)
{
return
new
RSVP
.
Promise
(
function
waitFormDataURLRead
(
resolve
,
reject
)
{
fr
.
addEventListener
(
"
load
"
,
function
handleDataURLRead
(
evt
)
{
resolve
(
evt
.
target
.
result
);
});
fr
.
addEventListener
(
"
error
"
,
reject
);
fr
.
readAsDataURL
(
blob
);
},
function
()
{
},
function
cancelReadBlobAsDataURL
()
{
fr
.
abort
();
});
}
...
...
@@ -50,7 +51,7 @@
}
function
itsANonResolvableTrap
(
resolve
,
reject
)
{
var
result
;
handle_event_callback
=
function
(
evt
)
{
handle_event_callback
=
function
handleEventCallback
(
evt
)
{
if
(
prevent_default
)
{
evt
.
stopPropagation
();
evt
.
preventDefault
();
...
...
@@ -66,10 +67,10 @@
callback_promise
=
result
;
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForEventCallbackResult
()
{
return
result
;
})
.
push
(
undefined
,
function
(
error
)
{
.
push
(
undefined
,
function
handleEventCallbackError
(
error
)
{
if
(
!
(
error
instanceof
RSVP
.
CancellationError
))
{
canceller
();
reject
(
error
);
...
...
@@ -147,11 +148,11 @@
error_list
=
[],
all_dependency_loaded_deferred
;
window
.
addEventListener
(
'
error
'
,
function
(
error
)
{
window
.
addEventListener
(
'
error
'
,
function
handleGlobalError
(
error
)
{
error_list
.
push
(
error
);
});
window
.
addEventListener
(
'
beforeunload
'
,
function
()
{
window
.
addEventListener
(
'
beforeunload
'
,
function
handleBeforeUnload
()
{
// XXX If another listener cancel the page unload,
// it will not restore renderJS crash report
is_page_unloaded
=
true
;
...
...
@@ -294,7 +295,7 @@
ResolvedMonitorError
.
prototype
=
new
Error
();
ResolvedMonitorError
.
prototype
.
constructor
=
ResolvedMonitorError
;
Monitor
=
function
()
{
Monitor
=
function
createMonitor
()
{
var
monitor
=
this
,
promise_list
=
[],
promise
,
...
...
@@ -316,8 +317,8 @@
promise_list
=
[];
}
promise
=
new
RSVP
.
Promise
(
function
(
done
,
fail
,
progress
)
{
reject
=
function
(
rejectedReason
)
{
promise
=
new
RSVP
.
Promise
(
function
promiseMonitor
(
done
,
fail
,
progress
)
{
reject
=
function
rejectMonitor
(
rejectedReason
)
{
if
(
resolved
)
{
return
;
}
...
...
@@ -330,33 +331,29 @@
notify
=
progress
;
},
canceller
);
monitor
.
cancel
=
function
()
{
monitor
.
cancel
=
function
cancelMonitor
()
{
if
(
resolved
)
{
return
;
}
resolved
=
true
;
promise
.
cancel
();
promise
.
fail
(
function
(
rejectedReason
)
{
promise
.
fail
(
function
rejectMonitorPromise
(
rejectedReason
)
{
monitor
.
isRejected
=
true
;
monitor
.
rejectedReason
=
rejectedReason
;
});
};
monitor
.
then
=
function
()
{
return
promise
.
then
.
apply
(
promise
,
arguments
);
};
monitor
.
fail
=
function
()
{
return
promise
.
fail
.
apply
(
promise
,
arguments
);
};
monitor
.
then
=
promise
.
then
.
bind
(
promise
);
monitor
.
fail
=
promise
.
fail
.
bind
(
promise
);
monitor
.
monitor
=
function
(
promise_to_monitor
)
{
monitor
.
monitor
=
function
startMonitor
(
promise_to_monitor
)
{
if
(
resolved
)
{
throw
new
ResolvedMonitorError
();
}
var
queue
=
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForPromiseToMonitor
()
{
return
promise_to_monitor
;
})
.
push
(
function
(
fulfillmentValue
)
{
.
push
(
function
handlePromiseToMonitorSuccess
(
fulfillmentValue
)
{
// Promise to monitor is fullfilled, remove it from the list
var
len
=
promise_list
.
length
,
sub_promise_to_monitor
,
...
...
@@ -370,7 +367,7 @@
}
}
promise_list
=
new_promise_list
;
},
function
(
rejectedReason
)
{
},
function
handlePromiseToMonitorError
(
rejectedReason
)
{
if
(
rejectedReason
instanceof
RSVP
.
CancellationError
)
{
if
(
!
(
promise_to_monitor
.
isFulfilled
&&
promise_to_monitor
.
isRejected
))
{
...
...
@@ -380,7 +377,7 @@
}
reject
(
rejectedReason
);
throw
rejectedReason
;
},
function
(
notificationValue
)
{
},
function
handlePromiseToMonitorNotification
(
notificationValue
)
{
notify
(
notificationValue
);
return
notificationValue
;
});
...
...
@@ -409,7 +406,7 @@
RenderJSGadget
.
prototype
.
__required_css_list
=
[];
RenderJSGadget
.
prototype
.
__required_js_list
=
[];
function
createMonitor
(
g
)
{
function
create
Gadget
Monitor
(
g
)
{
if
(
g
.
__monitor
!==
undefined
)
{
g
.
__monitor
.
cancel
();
}
...
...
@@ -417,19 +414,17 @@
g
.
__job_dict
=
{};
g
.
__job_list
=
[];
g
.
__job_triggered
=
false
;
g
.
__monitor
.
fail
(
function
(
error
)
{
g
.
__monitor
.
fail
(
function
handleGadgetMonitorError
(
error
)
{
if
(
!
(
error
instanceof
RSVP
.
CancellationError
))
{
return
g
.
aq_reportServiceError
(
error
);
}
}).
fail
(
function
(
error
)
{
// Crash the application if the acquisition generates an error.
return
letsCrash
(
error
);
});
// Crash the application if the acquisition generates an error.
}).
fail
(
letsCrash
);
}
function
clearGadgetInternalParameters
()
{
this
.
__sub_gadget_dict
=
{};
createMonitor
(
this
);
create
Gadget
Monitor
(
this
);
}
function
loadSubGadgetDOMDeclaration
()
{
...
...
@@ -443,7 +438,7 @@
context
=
this
;
function
prepareReportGadgetDeclarationError
(
scope
)
{
return
function
(
error
)
{
return
function
reportGadgetDeclarationError
(
error
)
{
var
aq_dict
=
context
.
__acquired_method_dict
||
{},
method_name
=
'
reportGadgetDeclarationError
'
;
if
(
aq_dict
.
hasOwnProperty
(
method_name
))
{
...
...
@@ -476,58 +471,56 @@
RenderJSGadget
.
__ready_list
=
[
clearGadgetInternalParameters
,
loadSubGadgetDOMDeclaration
];
RenderJSGadget
.
ready
=
function
(
callback
)
{
RenderJSGadget
.
ready
=
function
ready
(
callback
)
{
this
.
__ready_list
.
push
(
callback
);
return
this
;
};
RenderJSGadget
.
setState
=
function
(
state_dict
)
{
RenderJSGadget
.
setState
=
function
setState
(
state_dict
)
{
var
json_state
=
JSON
.
stringify
(
state_dict
);
this
.
__ready_list
.
unshift
(
function
()
{
this
.
__ready_list
.
unshift
(
function
setStateDefaultValue
()
{
this
.
state
=
JSON
.
parse
(
json_state
);
});
return
this
;
};
RenderJSGadget
.
onStateChange
=
function
(
callback
)
{
RenderJSGadget
.
onStateChange
=
function
onStateChange
(
callback
)
{
this
.
prototype
.
__state_change_callback
=
callback
;
return
this
;
};
RenderJSGadget
.
__service_list
=
[];
RenderJSGadget
.
declareService
=
function
(
callback
)
{
RenderJSGadget
.
declareService
=
function
declareService
(
callback
)
{
this
.
__service_list
.
push
(
callback
);
return
this
;
};
RenderJSGadget
.
onEvent
=
function
(
type
,
callback
,
use_capture
,
prevent_default
)
{
this
.
__service_list
.
push
(
function
()
{
RenderJSGadget
.
onEvent
=
function
onEvent
(
type
,
callback
,
use_capture
,
prevent_default
)
{
this
.
__service_list
.
push
(
function
startLoopEventListenerService
()
{
return
loopEventListener
(
this
.
element
,
type
,
use_capture
,
callback
.
bind
(
this
),
prevent_default
);
});
return
this
;
};
RenderJSGadget
.
onLoop
=
function
(
callback
,
delay
)
{
RenderJSGadget
.
onLoop
=
function
onLoop
(
callback
,
delay
)
{
if
(
delay
===
undefined
)
{
delay
=
0
;
}
this
.
__service_list
.
push
(
function
()
{
this
.
__service_list
.
push
(
function
handleServiceCallback
()
{
var
queue_loop
=
new
RSVP
.
Queue
(),
context
=
this
,
wait
=
function
()
{
wait
=
function
waitForLoopIteration
()
{
queue_loop
.
push
(
function
()
{
.
push
(
function
waitNextOnLoopDelay
()
{
return
RSVP
.
delay
(
delay
);
})
.
push
(
function
()
{
.
push
(
function
waitNextOnLoopAnimationFrame
()
{
// Only loop when the app has the focus
return
promiseAnimationFrame
();
})
.
push
(
function
()
{
.
push
(
function
executeOnLoopCallback
()
{
return
callback
.
apply
(
context
,
[]);
})
.
push
(
function
()
{
wait
();
});
.
push
(
wait
);
};
wait
();
return
queue_loop
;
...
...
@@ -537,7 +530,7 @@
function
runJob
(
gadget
,
name
,
callback
,
argument_list
)
{
var
job_promise
=
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForJobCallback
()
{
return
callback
.
apply
(
gadget
,
argument_list
);
});
if
(
gadget
.
__job_dict
.
hasOwnProperty
(
name
))
{
...
...
@@ -545,10 +538,10 @@
}
gadget
.
__job_dict
[
name
]
=
job_promise
;
gadget
.
__monitor
.
monitor
(
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForJobPromise
()
{
return
job_promise
;
})
.
push
(
undefined
,
function
(
error
)
{
.
push
(
undefined
,
function
handleJobError
(
error
)
{
if
(
!
(
error
instanceof
RSVP
.
CancellationError
))
{
throw
error
;
}
...
...
@@ -557,7 +550,7 @@
function
startService
(
gadget
)
{
gadget
.
__monitor
.
monitor
(
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
monitorAllServiceList
()
{
var
i
,
service_list
=
gadget
.
constructor
.
__service_list
,
job_list
=
gadget
.
__job_list
;
...
...
@@ -578,8 +571,8 @@
// gadget internal method, which trigger execution
// of a function inside a service
/////////////////////////////////////////////////////////////////
RenderJSGadget
.
declareJob
=
function
(
name
,
callback
)
{
this
.
prototype
[
name
]
=
function
()
{
RenderJSGadget
.
declareJob
=
function
declareJob
(
name
,
callback
)
{
this
.
prototype
[
name
]
=
function
triggerJob
()
{
var
context
=
this
,
argument_list
=
arguments
;
...
...
@@ -596,13 +589,13 @@
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareMethod
/////////////////////////////////////////////////////////////////
RenderJSGadget
.
declareMethod
=
function
(
name
,
callback
)
{
this
.
prototype
[
name
]
=
function
()
{
RenderJSGadget
.
declareMethod
=
function
declareMethod
(
name
,
callback
)
{
this
.
prototype
[
name
]
=
function
triggerMethod
()
{
var
context
=
this
,
argument_list
=
arguments
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForMethodCallback
()
{
return
callback
.
apply
(
context
,
argument_list
);
});
};
...
...
@@ -611,27 +604,27 @@
};
RenderJSGadget
.
declareMethod
(
'
getInterfaceList
'
,
function
()
{
.
declareMethod
(
'
getInterfaceList
'
,
function
getInterfaceList
()
{
// Returns the list of gadget prototype
return
this
.
__interface_list
;
})
.
declareMethod
(
'
getRequiredCSSList
'
,
function
()
{
.
declareMethod
(
'
getRequiredCSSList
'
,
function
getRequiredCSSList
()
{
// Returns a list of CSS required by the gadget
return
this
.
__required_css_list
;
})
.
declareMethod
(
'
getRequiredJSList
'
,
function
()
{
.
declareMethod
(
'
getRequiredJSList
'
,
function
getRequiredJSList
()
{
// Returns a list of JS required by the gadget
return
this
.
__required_js_list
;
})
.
declareMethod
(
'
getPath
'
,
function
()
{
.
declareMethod
(
'
getPath
'
,
function
getPath
()
{
// Returns the path of the code of a gadget
return
this
.
__path
;
})
.
declareMethod
(
'
getTitle
'
,
function
()
{
.
declareMethod
(
'
getTitle
'
,
function
getTitle
()
{
// Returns the title of a gadget
return
this
.
__title
;
})
.
declareMethod
(
'
getElement
'
,
function
()
{
.
declareMethod
(
'
getElement
'
,
function
getElement
()
{
// Returns the DOM Element of a gadget
// XXX Kept for compatibility. Use element property directly
if
(
this
.
element
===
undefined
)
{
...
...
@@ -639,24 +632,24 @@
}
return
this
.
element
;
})
.
declareMethod
(
'
changeState
'
,
function
(
state_dict
)
{
.
declareMethod
(
'
changeState
'
,
function
changeState
(
state_dict
)
{
var
next_onStateChange
=
new
RSVP
.
Queue
(),
previous_onStateCHange
,
context
=
this
;
if
(
context
.
hasOwnProperty
(
'
__previous_onStateChange
'
))
{
previous_onStateCHange
=
context
.
__previous_onStateChange
;
next_onStateChange
.
push
(
function
()
{
.
push
(
function
waitForPreviousStateChange
()
{
return
previous_onStateCHange
;
})
.
push
(
undefined
,
function
()
{
.
push
(
undefined
,
function
handlePreviousStateChangeError
()
{
// Run callback even if previous failed
return
;
});
}
context
.
__previous_onStateChange
=
next_onStateChange
;
return
next_onStateChange
.
push
(
function
()
{
.
push
(
function
checkStateModification
()
{
var
key
,
modified
=
false
,
previous_cancelled
=
context
.
hasOwnProperty
(
'
__modification_dict
'
),
...
...
@@ -678,10 +671,10 @@
if
(
modified
&&
context
.
__state_change_callback
!==
undefined
)
{
context
.
__modification_dict
=
modification_dict
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForStateChangeCallback
()
{
return
context
.
__state_change_callback
(
modification_dict
);
})
.
push
(
function
(
result
)
{
.
push
(
function
handleStateChangeSuccess
(
result
)
{
delete
context
.
__modification_dict
;
return
result
;
});
...
...
@@ -705,7 +698,7 @@
}
}
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForAcquireMethod
()
{
// Do not specify default __acquired_method_dict on prototype
// to prevent modifying this default value (with
// allowPublicAcquiredMethod for example)
...
...
@@ -716,7 +709,7 @@
}
throw
new
renderJS
.
AcquisitionError
(
"
aq_dynamic is not defined
"
);
})
.
push
(
undefined
,
function
(
error
)
{
.
push
(
undefined
,
function
handleAcquireMethodError
(
error
)
{
if
(
error
instanceof
renderJS
.
AcquisitionError
)
{
return
gadget
.
__aq_parent
(
method_name
,
argument_list
);
}
...
...
@@ -725,12 +718,12 @@
}
RenderJSGadget
.
declareAcquiredMethod
=
function
(
name
,
method_name_to_acquire
)
{
this
.
prototype
[
name
]
=
function
()
{
function
declareAcquiredMethod
(
name
,
method_name_to_acquire
)
{
this
.
prototype
[
name
]
=
function
acquireMethod
()
{
var
argument_list
=
Array
.
prototype
.
slice
.
call
(
arguments
,
0
),
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForAqParent
()
{
return
gadget
.
__aq_parent
(
method_name_to_acquire
,
argument_list
);
});
};
...
...
@@ -747,7 +740,7 @@
// RenderJSGadget.allowPublicAcquisition
/////////////////////////////////////////////////////////////////
RenderJSGadget
.
allowPublicAcquisition
=
function
(
method_name
,
callback
)
{
function
allowPublicAcquisition
(
method_name
,
callback
)
{
this
.
prototype
.
__acquired_method_dict
[
method_name
]
=
callback
;
// Allow chain
...
...
@@ -756,10 +749,11 @@
// Set aq_parent on gadget_instance which call acquire on parent_gadget
function
setAqParent
(
gadget_instance
,
parent_gadget
)
{
gadget_instance
.
__aq_parent
=
function
(
method_name
,
argument_list
)
{
return
acquire
.
apply
(
parent_gadget
,
[
gadget_instance
,
method_name
,
argument_list
]);
};
gadget_instance
.
__aq_parent
=
function
__aq_parent
(
method_name
,
argument_list
)
{
return
acquire
.
apply
(
parent_gadget
,
[
gadget_instance
,
method_name
,
argument_list
]);
};
}
/////////////////////////////////////////////////////////////////
...
...
@@ -795,19 +789,13 @@
/////////////////////////////////////////////////////////////////
function
privateDeclarePublicGadget
(
url
,
options
,
parent_gadget
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
renderJS
.
declareGadgetKlass
(
url
)
// gadget loading should not be interrupted
// if not, gadget's definition will not be complete
//.then will return another promise
//so loading_klass_promise can't be cancel
.
then
(
function
(
result
)
{
return
result
;
});
})
// Get the gadget class and instanciate it
.
push
(
function
(
Klass
)
{
return
renderJS
.
declareGadgetKlass
(
url
)
// gadget loading should not be interrupted
// if not, gadget's definition will not be complete
//.then will return another promise
//so loading_klass_promise can't be cancel
.
then
(
function
createPrivateInstanceFromKlass
(
Klass
)
{
// Get the gadget class and instanciate it
if
(
options
.
element
===
undefined
)
{
options
.
element
=
document
.
createElement
(
"
div
"
);
}
...
...
@@ -876,12 +864,12 @@
gadget_instance
=
new
RenderJSIframeGadget
();
setAqParent
(
gadget_instance
,
parent_gadget
);
iframe
=
document
.
createElement
(
"
iframe
"
);
iframe
.
addEventListener
(
'
error
'
,
function
(
error
)
{
iframe
.
addEventListener
(
'
error
'
,
function
handleIframeError
(
error
)
{
iframe_loading_deferred
.
reject
(
error
);
});
iframe
.
addEventListener
(
'
load
'
,
function
()
{
iframe
.
addEventListener
(
'
load
'
,
function
handleIframeLoad
()
{
return
RSVP
.
timeout
(
5000
)
.
fail
(
function
()
{
.
fail
(
function
triggerIframeTimeout
()
{
iframe_loading_deferred
.
reject
(
new
Error
(
'
Timeout while loading:
'
+
url
)
);
...
...
@@ -906,46 +894,51 @@
});
// Create new method from the declareMethod call inside the iframe
gadget_instance
.
__chan
.
bind
(
"
declareMethod
"
,
function
(
trans
,
method_name
)
{
gadget_instance
[
method_name
]
=
function
()
{
gadget_instance
.
__chan
.
bind
(
"
declareMethod
"
,
function
handleChannelDeclareMethod
(
trans
,
method_name
)
{
gadget_instance
[
method_name
]
=
function
triggerChannelDeclareMethod
()
{
var
argument_list
=
arguments
,
wait_promise
=
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
gadget_instance
.
__chan
.
call
({
method
:
"
methodCall
"
,
params
:
[
method_name
,
Array
.
prototype
.
slice
.
call
(
argument_list
,
0
)],
success
:
resolve
,
error
:
reject
});
});
wait_promise
=
new
RSVP
.
Promise
(
function
handleChannelCall
(
resolve
,
reject
)
{
gadget_instance
.
__chan
.
call
({
method
:
"
methodCall
"
,
params
:
[
method_name
,
Array
.
prototype
.
slice
.
call
(
argument_list
,
0
)],
success
:
resolve
,
error
:
reject
});
}
);
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForChannelCall
()
{
return
wait_promise
;
});
};
return
"
OK
"
;
});
}
);
// Wait for the iframe to be loaded before continuing
gadget_instance
.
__chan
.
bind
(
"
ready
"
,
function
(
trans
)
{
gadget_instance
.
__chan
.
bind
(
"
ready
"
,
function
handleChannelReady
(
trans
)
{
iframe_loading_deferred
.
resolve
(
gadget_instance
);
return
"
OK
"
;
});
gadget_instance
.
__chan
.
bind
(
"
failed
"
,
function
(
trans
,
params
)
{
iframe_loading_deferred
.
reject
(
params
);
return
"
OK
"
;
});
gadget_instance
.
__chan
.
bind
(
"
acquire
"
,
function
(
trans
,
params
)
{
gadget_instance
.
__aq_parent
.
apply
(
gadget_instance
,
params
)
.
then
(
function
(
g
)
{
trans
.
complete
(
g
);
}).
fail
(
function
(
e
)
{
trans
.
error
(
e
.
toString
());
});
trans
.
delayReturn
(
true
);
});
gadget_instance
.
__chan
.
bind
(
"
failed
"
,
function
handleChannelFail
(
trans
,
params
)
{
iframe_loading_deferred
.
reject
(
params
);
return
"
OK
"
;
});
gadget_instance
.
__chan
.
bind
(
"
acquire
"
,
function
handleChannelAcquire
(
trans
,
params
)
{
gadget_instance
.
__aq_parent
.
apply
(
gadget_instance
,
params
)
.
then
(
trans
.
complete
)
.
fail
(
function
handleChannelAcquireError
(
e
)
{
trans
.
error
(
e
.
toString
());
});
trans
.
delayReturn
(
true
);
});
return
iframe_loading_deferred
.
promise
;
}
...
...
@@ -956,10 +949,10 @@
function
privateDeclareDataUrlGadget
(
url
,
options
,
parent_gadget
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForDataUrlAjax
()
{
return
ajax
(
url
);
})
.
push
(
function
(
xhr
)
{
.
push
(
function
handleDataURLAjaxResponse
(
xhr
)
{
// Insert a "base" element, in order to resolve all relative links
// which could get broken with a data url
var
doc
=
(
new
DOMParser
()).
parseFromString
(
xhr
.
responseText
,
...
...
@@ -972,7 +965,7 @@
{
type
:
"
text/html;charset=UTF-8
"
});
return
readBlobAsDataURL
(
blob
);
})
.
push
(
function
(
data_url
)
{
.
push
(
function
handleDataURL
(
data_url
)
{
return
privateDeclareIframeGadget
(
data_url
,
options
,
parent_gadget
);
});
}
...
...
@@ -981,7 +974,7 @@
// RenderJSGadget.declareGadget
/////////////////////////////////////////////////////////////////
RenderJSGadget
.
declareMethod
(
'
declareGadget
'
,
function
(
url
,
options
)
{
.
declareMethod
(
'
declareGadget
'
,
function
declareGadget
(
url
,
options
)
{
var
parent_gadget
=
this
;
if
(
options
===
undefined
)
{
...
...
@@ -995,7 +988,7 @@
url
=
renderJS
.
getAbsoluteURL
(
url
,
this
.
__path
);
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForPrivateDeclareGadget
()
{
var
method
;
if
(
options
.
sandbox
===
"
public
"
)
{
method
=
privateDeclarePublicGadget
;
...
...
@@ -1010,7 +1003,7 @@
return
method
(
url
,
options
,
parent_gadget
);
})
// Set the HTML context
.
push
(
function
(
gadget_instance
)
{
.
push
(
function
setGadgetInstanceHTMLContext
(
gadget_instance
)
{
var
i
,
scope
,
queue
=
new
RSVP
.
Queue
();
...
...
@@ -1019,7 +1012,7 @@
return
gadget_instance
;
}
function
ready_executable_wrapper
(
fct
)
{
return
function
()
{
return
function
executeReadyWrapper
()
{
return
fct
.
call
(
gadget_instance
,
gadget_instance
);
};
}
...
...
@@ -1063,13 +1056,14 @@
return
queue
;
});
})
.
declareMethod
(
'
getDeclaredGadget
'
,
function
(
gadget_scope
)
{
if
(
!
this
.
__sub_gadget_dict
.
hasOwnProperty
(
gadget_scope
))
{
throw
new
Error
(
"
Gadget scope '
"
+
gadget_scope
+
"
' is not known.
"
);
}
return
this
.
__sub_gadget_dict
[
gadget_scope
];
})
.
declareMethod
(
'
dropGadget
'
,
function
(
gadget_scope
)
{
.
declareMethod
(
'
getDeclaredGadget
'
,
function
getDeclaredGadget
(
gadget_scope
)
{
if
(
!
this
.
__sub_gadget_dict
.
hasOwnProperty
(
gadget_scope
))
{
throw
new
Error
(
"
Gadget scope '
"
+
gadget_scope
+
"
' is not known.
"
);
}
return
this
.
__sub_gadget_dict
[
gadget_scope
];
})
.
declareMethod
(
'
dropGadget
'
,
function
dropGadget
(
gadget_scope
)
{
if
(
!
this
.
__sub_gadget_dict
.
hasOwnProperty
(
gadget_scope
))
{
throw
new
Error
(
"
Gadget scope '
"
+
gadget_scope
+
"
' is not known.
"
);
}
...
...
@@ -1080,7 +1074,7 @@
/////////////////////////////////////////////////////////////////
// renderJS selector
/////////////////////////////////////////////////////////////////
renderJS
=
function
(
selector
)
{
renderJS
=
function
getLoadingGadget
(
selector
)
{
var
result
;
if
(
selector
===
window
)
{
// window is the 'this' value when loading a javascript file
...
...
@@ -1096,7 +1090,7 @@
/////////////////////////////////////////////////////////////////
// renderJS.AcquisitionError
/////////////////////////////////////////////////////////////////
renderJS
.
AcquisitionError
=
function
(
message
)
{
renderJS
.
AcquisitionError
=
function
createAcquisitionError
(
message
)
{
this
.
name
=
"
AcquisitionError
"
;
if
((
message
!==
undefined
)
&&
(
typeof
message
!==
"
string
"
))
{
throw
new
TypeError
(
'
You must pass a string.
'
);
...
...
@@ -1110,7 +1104,7 @@
/////////////////////////////////////////////////////////////////
// renderJS.getAbsoluteURL
/////////////////////////////////////////////////////////////////
renderJS
.
getAbsoluteURL
=
function
(
url
,
base_url
)
{
renderJS
.
getAbsoluteURL
=
function
getAbsoluteURL
(
url
,
base_url
)
{
if
(
base_url
&&
url
)
{
return
new
URL
(
url
,
base_url
).
href
;
}
...
...
@@ -1120,7 +1114,7 @@
/////////////////////////////////////////////////////////////////
// renderJS.declareJS
/////////////////////////////////////////////////////////////////
renderJS
.
declareJS
=
function
(
url
,
container
,
pop
)
{
renderJS
.
declareJS
=
function
declareJS
(
url
,
container
,
pop
)
{
// https://www.html5rocks.com/en/tutorials/speed/script-loading/
// Prevent infinite recursion if loading render.js
// more than once
...
...
@@ -1129,28 +1123,30 @@
result
=
RSVP
.
resolve
();
}
else
{
javascript_registration_dict
[
url
]
=
null
;
result
=
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
newScript
;
newScript
=
document
.
createElement
(
'
script
'
);
newScript
.
async
=
false
;
newScript
.
type
=
'
text/javascript
'
;
newScript
.
onload
=
function
()
{
if
(
pop
===
true
)
{
// Drop the current loading klass info used by selector
gadget_loading_klass_list
.
shift
();
}
resolve
();
};
newScript
.
onerror
=
function
(
e
)
{
if
(
pop
===
true
)
{
// Drop the current loading klass info used by selector
gadget_loading_klass_list
.
shift
();
}
reject
(
e
);
};
newScript
.
src
=
url
;
container
.
appendChild
(
newScript
);
});
result
=
new
RSVP
.
Promise
(
function
waitForJSLoadEvent
(
resolve
,
reject
)
{
var
newScript
;
newScript
=
document
.
createElement
(
'
script
'
);
newScript
.
async
=
false
;
newScript
.
type
=
'
text/javascript
'
;
newScript
.
onload
=
function
triggerJSLoaded
()
{
if
(
pop
===
true
)
{
// Drop the current loading klass info used by selector
gadget_loading_klass_list
.
shift
();
}
resolve
();
};
newScript
.
onerror
=
function
triggerJSNotLoaded
(
e
)
{
if
(
pop
===
true
)
{
// Drop the current loading klass info used by selector
gadget_loading_klass_list
.
shift
();
}
reject
(
e
);
};
newScript
.
src
=
url
;
container
.
appendChild
(
newScript
);
}
);
}
return
result
;
};
...
...
@@ -1158,7 +1154,7 @@
/////////////////////////////////////////////////////////////////
// renderJS.declareCSS
/////////////////////////////////////////////////////////////////
renderJS
.
declareCSS
=
function
(
url
,
container
)
{
renderJS
.
declareCSS
=
function
declareCSS
(
url
,
container
)
{
// https://github.com/furf/jquery-getCSS/blob/master/jquery.getCSS.js
// No way to cleanly check if a css has been loaded
// So, always resolve the promise...
...
...
@@ -1167,19 +1163,17 @@
if
(
stylesheet_registration_dict
.
hasOwnProperty
(
url
))
{
result
=
RSVP
.
resolve
();
}
else
{
result
=
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
result
=
new
RSVP
.
Promise
(
function
waitForCSSLoadEvent
(
resolve
,
reject
)
{
var
link
;
link
=
document
.
createElement
(
'
link
'
);
link
.
rel
=
'
stylesheet
'
;
link
.
type
=
'
text/css
'
;
link
.
href
=
url
;
link
.
onload
=
function
()
{
link
.
onload
=
function
triggerCSSLoaded
()
{
stylesheet_registration_dict
[
url
]
=
null
;
resolve
();
};
link
.
onerror
=
function
(
e
)
{
reject
(
e
);
};
link
.
onerror
=
reject
;
container
.
appendChild
(
link
);
});
}
...
...
@@ -1195,7 +1189,7 @@
key
,
parsed_html
;
// Class inheritance
tmp_constructor
=
function
()
{
tmp_constructor
=
function
createSuperKlass
()
{
RenderJSGadget
.
call
(
this
);
};
tmp_constructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
...
...
@@ -1241,7 +1235,7 @@
return
tmp_constructor
;
}
renderJS
.
declareGadgetKlass
=
function
(
url
)
{
renderJS
.
declareGadgetKlass
=
function
declareGadgetKlass
(
url
)
{
if
(
gadget_model_defer_dict
.
hasOwnProperty
(
url
))
{
// Return klass object if it already exists
return
gadget_model_defer_dict
[
url
].
promise
;
...
...
@@ -1254,10 +1248,10 @@
// Fetch the HTML page and parse it
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForGadgetKlassAjax
()
{
return
ajax
(
url
);
})
.
push
(
function
(
result
)
{
.
push
(
function
handleGadgetKlassAjax
(
result
)
{
tmp_constructor
=
parse
(
result
,
url
);
var
fragment
=
document
.
createDocumentFragment
(),
promise_list
=
[],
...
...
@@ -1279,11 +1273,11 @@
document
.
head
.
appendChild
(
fragment
);
return
RSVP
.
all
(
promise_list
);
})
.
push
(
function
()
{
.
push
(
function
handleGadgetKlassLoadingSuccess
()
{
defer
.
resolve
(
tmp_constructor
);
return
tmp_constructor
;
})
.
push
(
undefined
,
function
(
e
)
{
.
push
(
undefined
,
function
handleGadgetKlassLoadingError
(
e
)
{
// Drop the current loading klass info used by selector
// even in case of error
defer
.
reject
(
e
);
...
...
@@ -1295,7 +1289,7 @@
// renderJS.clearGadgetKlassList
/////////////////////////////////////////////////////////////////
// For test purpose only
renderJS
.
clearGadgetKlassList
=
function
()
{
renderJS
.
clearGadgetKlassList
=
function
clearGadgetKlassList
()
{
gadget_model_defer_dict
=
{};
javascript_registration_dict
=
{};
stylesheet_registration_dict
=
{};
...
...
@@ -1304,53 +1298,54 @@
/////////////////////////////////////////////////////////////////
// renderJS.parseGadgetHTMLDocument
/////////////////////////////////////////////////////////////////
renderJS
.
parseGadgetHTMLDocument
=
function
(
document_element
,
url
)
{
var
settings
=
{
title
:
""
,
interface_list
:
[],
required_css_list
:
[],
required_js_list
:
[]
},
i
,
element
;
if
(
!
url
||
!
isAbsoluteOrDataURL
.
test
(
url
))
{
throw
new
Error
(
"
The url should be absolute:
"
+
url
);
}
renderJS
.
parseGadgetHTMLDocument
=
function
parseGadgetHTMLDocument
(
document_element
,
url
)
{
var
settings
=
{
title
:
""
,
interface_list
:
[],
required_css_list
:
[],
required_js_list
:
[]
},
i
,
element
;
if
(
!
url
||
!
isAbsoluteOrDataURL
.
test
(
url
))
{
throw
new
Error
(
"
The url should be absolute:
"
+
url
);
}
if
(
document_element
.
nodeType
===
9
)
{
settings
.
title
=
document_element
.
title
;
if
(
document_element
.
head
!==
null
)
{
for
(
i
=
0
;
i
<
document_element
.
head
.
children
.
length
;
i
+=
1
)
{
element
=
document_element
.
head
.
children
[
i
];
if
(
element
.
href
!==
null
)
{
// XXX Manage relative URL during extraction of URLs
// element.href returns absolute URL in firefox but "" in chrome;
if
(
element
.
rel
===
"
stylesheet
"
)
{
settings
.
required_css_list
.
push
(
renderJS
.
getAbsoluteURL
(
element
.
getAttribute
(
"
href
"
),
url
)
);
}
else
if
(
element
.
nodeName
===
"
SCRIPT
"
&&
(
element
.
type
===
"
text/javascript
"
||
!
element
.
type
))
{
settings
.
required_js_list
.
push
(
renderJS
.
getAbsoluteURL
(
element
.
getAttribute
(
"
src
"
),
url
)
);
}
else
if
(
element
.
rel
===
"
http://www.renderjs.org/rel/interface
"
)
{
settings
.
interface_list
.
push
(
renderJS
.
getAbsoluteURL
(
element
.
getAttribute
(
"
href
"
),
url
)
);
if
(
document_element
.
nodeType
===
9
)
{
settings
.
title
=
document_element
.
title
;
if
(
document_element
.
head
!==
null
)
{
for
(
i
=
0
;
i
<
document_element
.
head
.
children
.
length
;
i
+=
1
)
{
element
=
document_element
.
head
.
children
[
i
];
if
(
element
.
href
!==
null
)
{
// XXX Manage relative URL during extraction of URLs
// element.href returns absolute URL in firefox but "" in chrome;
if
(
element
.
rel
===
"
stylesheet
"
)
{
settings
.
required_css_list
.
push
(
renderJS
.
getAbsoluteURL
(
element
.
getAttribute
(
"
href
"
),
url
)
);
}
else
if
(
element
.
nodeName
===
"
SCRIPT
"
&&
(
element
.
type
===
"
text/javascript
"
||
!
element
.
type
))
{
settings
.
required_js_list
.
push
(
renderJS
.
getAbsoluteURL
(
element
.
getAttribute
(
"
src
"
),
url
)
);
}
else
if
(
element
.
rel
===
"
http://www.renderjs.org/rel/interface
"
)
{
settings
.
interface_list
.
push
(
renderJS
.
getAbsoluteURL
(
element
.
getAttribute
(
"
href
"
),
url
)
);
}
}
}
}
}
else
{
throw
new
Error
(
"
The first parameter should be an HTMLDocument
"
);
}
}
else
{
throw
new
Error
(
"
The first parameter should be an HTMLDocument
"
);
}
return
settings
;
};
return
settings
;
};
/////////////////////////////////////////////////////////////////
// global
...
...
@@ -1370,7 +1365,7 @@
// is triggered before everything was ready.
// (For instance, the HTML-tag for the self gadget gets inserted after
// page load)
renderJS
.
manualBootstrap
=
function
()
{
renderJS
.
manualBootstrap
=
function
manualBootstrap
()
{
all_dependency_loaded_deferred
.
resolve
();
};
document
.
addEventListener
(
'
DOMContentLoaded
'
,
...
...
@@ -1398,7 +1393,7 @@
TmpConstructor
.
__template_element
.
appendChild
(
fragment
);
return
RSVP
.
all
([
root_gadget
.
getRequiredJSList
(),
root_gadget
.
getRequiredCSSList
()])
.
then
(
function
(
all_list
)
{
.
then
(
function
handleRequireDependencyList
(
all_list
)
{
var
i
,
js_list
=
all_list
[
0
],
css_list
=
all_list
[
1
];
...
...
@@ -1409,14 +1404,14 @@
stylesheet_registration_dict
[
css_list
[
i
]]
=
null
;
}
gadget_loading_klass_list
.
shift
();
}).
then
(
function
()
{
}).
then
(
function
createMutationObserver
()
{
// select the target node
var
target
=
document
.
querySelector
(
'
body
'
),
// create an observer instance
observer
=
new
MutationObserver
(
function
(
mutations
)
{
observer
=
new
MutationObserver
(
function
observeMutatios
(
mutations
)
{
var
i
,
k
,
len
,
len2
,
node
,
added_list
;
mutations
.
forEach
(
function
(
mutation
)
{
mutations
.
forEach
(
function
observerMutation
(
mutation
)
{
if
(
mutation
.
type
===
'
childList
'
)
{
len
=
mutation
.
removedNodes
.
length
;
...
...
@@ -1425,7 +1420,7 @@
if
(
node
.
nodeType
===
Node
.
ELEMENT_NODE
)
{
if
(
node
.
hasAttribute
(
"
data-gadget-url
"
)
&&
(
node
.
_gadget
!==
undefined
))
{
createMonitor
(
node
.
_gadget
);
create
Gadget
Monitor
(
node
.
_gadget
);
}
added_list
=
node
.
querySelectorAll
(
"
[data-gadget-url]
"
);
...
...
@@ -1433,7 +1428,7 @@
for
(
k
=
0
;
k
<
len2
;
k
+=
1
)
{
node
=
added_list
[
k
];
if
(
node
.
_gadget
!==
undefined
)
{
createMonitor
(
node
.
_gadget
);
create
Gadget
Monitor
(
node
.
_gadget
);
}
}
}
...
...
@@ -1484,13 +1479,13 @@
function
createLastAcquisitionGadget
()
{
var
last_acquisition_gadget
=
new
RenderJSGadget
();
last_acquisition_gadget
.
__acquired_method_dict
=
{
reportServiceError
:
function
(
param_list
)
{
reportServiceError
:
function
reportServiceError
(
param_list
)
{
letsCrash
(
param_list
[
0
]);
}
};
// Stop acquisition on the last acquisition gadget
// Do not put this on the klass, as their could be multiple instances
last_acquisition_gadget
.
__aq_parent
=
function
(
method_name
)
{
last_acquisition_gadget
.
__aq_parent
=
function
__aq_parent
(
method_name
)
{
throw
new
renderJS
.
AcquisitionError
(
"
No gadget provides
"
+
method_name
);
...
...
@@ -1538,7 +1533,7 @@
];
// Inform parent gadget about declareMethod calls here.
notifyDeclareMethod
=
function
(
name
)
{
notifyDeclareMethod
=
function
notifyDeclareMethod
(
name
)
{
declare_method_list_waiting
.
push
(
name
);
};
...
...
@@ -1551,13 +1546,13 @@
loading_result
=
RSVP
.
any
([
channel_defer
.
promise
,
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForParentChannelCreation
()
{
// Expect the channel to parent to be usable after 1 second
// If not, consider the gadget as the root
// Drop all iframe channel communication
return
RSVP
.
delay
(
1000
);
})
.
push
(
function
()
{
.
push
(
function
handleParentChannelCreation
()
{
real_result_list
[
2
]
=
undefined
;
return
real_result_list
;
})
...
...
@@ -1567,20 +1562,22 @@
window
:
window
.
parent
,
origin
:
"
*
"
,
scope
:
"
renderJS
"
,
onReady
:
function
()
{
onReady
:
function
onChannelReady
()
{
var
k
,
len
;
// Channel is ready, so now declare all methods
notifyDeclareMethod
=
function
(
name
)
{
notifyDeclareMethod
=
function
notifyDeclareMethod
(
name
)
{
declare_method_list_waiting
.
push
(
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
embedded_channel
.
call
({
method
:
"
declareMethod
"
,
params
:
name
,
success
:
resolve
,
error
:
reject
});
})
new
RSVP
.
Promise
(
function
promiseChannelDeclareMethodCall
(
resolve
,
reject
)
{
embedded_channel
.
call
({
method
:
"
declareMethod
"
,
params
:
name
,
success
:
resolve
,
error
:
reject
});
}
)
);
};
...
...
@@ -1596,7 +1593,7 @@
}
// Surcharge declareMethod to inform parent window
TmpConstructor
.
declareMethod
=
function
(
name
,
callback
)
{
TmpConstructor
.
declareMethod
=
function
declareMethod
(
name
,
callback
)
{
var
result
=
RenderJSGadget
.
declareMethod
.
apply
(
this
,
[
name
,
callback
]
...
...
@@ -1633,11 +1630,11 @@
return
root_gadget
;
}
function
ready_executable_wrapper
(
fct
)
{
return
function
(
g
)
{
return
function
wrapReadyFunction
(
g
)
{
return
fct
.
call
(
g
,
g
);
};
}
TmpConstructor
.
ready
(
function
()
{
TmpConstructor
.
ready
(
function
startServiceInReady
()
{
return
startService
(
this
);
});
...
...
@@ -1656,35 +1653,32 @@
embedded_channel
)
{
// Define __aq_parent to inform parent window
root_gadget
.
__aq_parent
=
TmpConstructor
.
prototype
.
__aq_parent
=
function
(
method_name
,
argument_list
,
time_out
)
{
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
embedded_channel
.
call
({
method
:
"
acquire
"
,
params
:
[
method_name
,
argument_list
],
success
:
function
(
s
)
{
resolve
(
s
);
},
error
:
function
(
e
)
{
reject
(
e
);
},
timeout
:
time_out
});
});
TmpConstructor
.
prototype
.
__aq_parent
=
function
aq_parent
(
method_name
,
argument_list
,
time_out
)
{
return
new
RSVP
.
Promise
(
function
waitForChannelAcquire
(
resolve
,
reject
)
{
embedded_channel
.
call
({
method
:
"
acquire
"
,
params
:
[
method_name
,
argument_list
],
success
:
resolve
,
error
:
reject
,
timeout
:
time_out
});
}
);
};
// bind calls to renderJS method on the instance
embedded_channel
.
bind
(
"
methodCall
"
,
function
(
trans
,
v
)
{
embedded_channel
.
bind
(
"
methodCall
"
,
function
methodCall
(
trans
,
v
)
{
root_gadget
[
v
[
0
]].
apply
(
root_gadget
,
v
[
1
])
.
push
(
function
(
g
)
{
trans
.
complete
(
g
);
},
function
(
e
)
{
trans
.
error
(
e
.
toString
());
});
.
push
(
trans
.
complete
,
function
handleMethodCallError
(
e
)
{
trans
.
error
(
e
.
toString
());
});
trans
.
delayReturn
(
true
);
});
}
...
...
@@ -1698,11 +1692,11 @@
declare_method_list_waiting
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
waitForLoadingGadget
()
{
// Wait for the loading gadget to be created
return
wait_for_gadget_loaded
;
})
.
push
(
function
(
result_list
)
{
.
push
(
function
handleLoadingGadget
(
result_list
)
{
TmpConstructor
=
result_list
[
0
];
root_gadget
=
result_list
[
1
];
embedded_channel
=
result_list
[
2
];
...
...
@@ -1710,11 +1704,11 @@
// Wait for all the gadget dependencies to be loaded
return
all_dependency_loaded_deferred
.
promise
;
})
.
push
(
function
()
{
.
push
(
function
waitForDeclareMethodList
()
{
// Wait for all methods to be correctly declared
return
RSVP
.
all
(
declare_method_list_waiting
);
})
.
push
(
function
(
result_list
)
{
.
push
(
function
waitForMutationObserver
(
result_list
)
{
if
(
embedded_channel
!==
undefined
)
{
finishAqParentConfiguration
(
TmpConstructor
,
root_gadget
,
embedded_channel
);
...
...
@@ -1722,16 +1716,16 @@
// Check all DOM modifications to correctly start/stop services
return
configureMutationObserver
(
TmpConstructor
,
url
,
root_gadget
);
})
.
push
(
function
()
{
.
push
(
function
waitForReadyList
()
{
// Trigger all ready functions
return
triggerReadyList
(
TmpConstructor
,
root_gadget
);
})
.
push
(
function
()
{
.
push
(
function
notifyReady
()
{
if
(
embedded_channel
!==
undefined
)
{
embedded_channel
.
notify
({
method
:
"
ready
"
});
}
})
.
push
(
undefined
,
function
(
e
)
{
.
push
(
undefined
,
function
handleBootstrapError
(
e
)
{
letsCrash
(
e
);
if
(
embedded_channel
!==
undefined
)
{
embedded_channel
.
notify
({
method
:
"
failed
"
,
params
:
e
.
toString
()});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment