SlideShare une entreprise Scribd logo
1  sur  77
Télécharger pour lire hors ligne
ES2015
ENHANCEANGULAR1.XAPPLICATIONS
Ernest Nowacki
AGENDA
What?
Why?
How?
Raw meat!
WHAT?
ES2015 is a significant and the first update to the
language since ES5 was standardized in 2009
FEATURES
let + const arrows classes
enhanced object literals modules promises
template strings destructuring default + rest + spread
iterators + for..of generators subclassable built-ins
map + set + weakmap + weakset proxies symbols
math + number + string + array + object APIs binary and octal literals tail calls
unicode
WHY?
This Ecma Standard has been adopted by the General
Assembly of June 2015.
PROS
Backward compatibility
Less boilerplate
Better maintainability
Better preparation for Angular 2.0
Easier for newcomers
Staying current
Slide from Jafar Husain's talk: ES7 evolution of JS
CONS
Browser compatibility
Require transpilation
No established best practises
New things to learn
http://kangax.github.io/compat-table/es6
HOW?
http://babeljs.io
SIMPLEINTEGRATION
var gulp = require("gulp");
var babel = require("gulp­babel");
gulp.task("default", function () {
    return gulp.src("src/app.js")
        .pipe(babel())
        .pipe(gulp.dest("dist"));
});
ONLINEPLAYGROUND
http://babeljs.io/repl
WEBPACK
http://webpack.github.io
JUMPSTARTWEBPACK+BABEL+
ANGULAR:GULP-ANGULAR
yo gulp­angular
DIVEDEEP
LET,CONST,BLOCKSCOPE
let a = 2;
{
    let a = 3;
    console.log( a );   // 3
}
console.log( a );       // 2
{
    const a = 2;
    console.log( a );   // 2
    a = 3;              // TypeError!
}
BLOCKSCOPINGES5VSES2015
if (true) {
    function weather() {
        console.log( "Sun" );
    }
} else {
    function weather() {
        console.log( "Rain" );
    }
}
weather();
ES5
var funcs = [];
for (var i = 0; i < 5; i++) {
    funcs.push( function(){
        console.log( i );
    });
}
funcs[3]();     // 5
ES2015
var funcs = [];
for (let i = 0; i < 5; i++) {
    funcs.push( function(){
        console.log( i );
    });
}
funcs[3]();     // 3
TEMPORALDEADZONE
(TDZ)
TEMPORALDEADZONE(TDZ)
console.log( a );   // undefined
console.log( b );   // ReferenceError!
var a;
let b;
if( typeof a === 'undefined' ){
    console.log('a is ok');
}
if( typeof b === 'undefined' ){ //ReferenceError!
    console.log('b is ok');
}
let b;
*it's not an issue when using babel
(NOTSO)CONST
const arr = ['dog', 'cat', 'snake'];
arr.push('fish');
console.log(arr); // ['dog', 'cat', 'snake', 'fish'];
EVOLUTIONOFCONTROLLERS
BEGINING
'use strict';
angular.module('app').controller('TodoCtrl', function($scope){
    $scope.todos = [];
    $scope.newTodo = '' ;
    $scope.addTodo = function(todo){
        $scope.todos.push(todo);
    }
    $scope.removeTodo = function (todo) {
        $scope.todos.splice($scope.todos.indexOf(todo), 1);
    };
});
<div ng­controller="TodoCtrl">
    <input type="text" ng­model="newTodo">
    <button type="button" ng­click="addTodo(newTodo)"></button>
    <ul>
        <li ng­repeat="todo in todos">
            {{todo}}
            <button type="button" ng­click="removeTodo(todo)"></button>
        </li>
    </ul>
</div>
SMALLIMPROVEMENTS
(function (){
    'use strict';
    angular.module('app').controller('TodoCtrl', TodoCtrl);
    function TodoCtrl($scope){
        $scope.todos = [];
        $scope.newTodo = '' ;
        $scope.addTodo = function addTodo(todo){
            $scope.todos.push(todo);
        }
        $scope.removeTodo = function removeTodo(todo) {
            $scope.todos.splice($scope.todos.indexOf(todo), 1);
        };
    }
});
controllerAs
<div ng­controller="TodoCtrl as ctrl">
    <input type="text" ng­model="ctrl.newTodo">
    <button type="button" ng­click="ctrl.addTodo(newTodo)"></button>
    <ul>
        <li ng­repeat="todo in ctrl.todos">
            {{todo}}
            <button type="button" ng­click="ctrl.removeTodo(todo)"></button
        </li>
    </ul>
</div>
(function (){
    'use strict';
    angular.module('app').controller('TodoCtrl', TodoCtrl);
    function TodoCtrl(){
        this.todos = [];
        this.newTodo = '' ;
        this.addTodo = function addTodo(todo){
            this.todos.push(todo);
        }
        this.removeTodo = function removeTodo(todo) {
            this.todos.splice(this.todos.indexOf(todo), 1);
        };
    }
});
ALMOSTTHEREBUT..
FINALFORM
(function (){
    'use strict';
    angular.module('app').controller('TodoCtrl', TodoCtrl);
    function TodoCtrl(){
        var vm = this;
        vm.todos = [];
        vm.newTodo = '' ;
        vm.addTodo = addTodo;
        vm.removeTodo = removeTodo;
        function addTodo(todo){
            vm.todos.push(todo);
        }
        function removeTodo(todo) {
            vm.todos.splice(vm.todos.indexOf(todo), 1);
ES6CLASSES
'use strict';
class TodoCtrl{
    constructor(){
        this.todos = [];
        this.newTodo = '';
    }
    addTodo(todo){
        this.todos.push(todo);
    }
    removeTodo(todo) {
        this.todos.splice(this.todos.indexOf(todo), 1);
    };
}
angular.module('app').controller('TodoCtrl', TodoCtrl);
ORLY?
ES5PROTOTYPES
function TodoCtrl(){
    this.todos = [];
    this.newTodo = '';
}
TodoCtrl.prototype.addTodo = function(todo){
    this.todos.push(todo);
}
TodoCtrl.prototype.removeTodo = function(todo) {
    this.todos.splice(this.todos.indexOf(todo), 1);
};
angular.module('app').controller('TodoCtrl', TodoCtrl);
SETTERSANDGETTERS
class MyClass {
    constructor(){
        this._prop = 0;
    }
    get prop() {
        console.log('getter');
        return this._prop;
    }
    set prop(value) {
        console.log('setter: ' + value);
        this._prop = value;
    }
}
let inst = new MyClass();
inst = 123; // setter + 123
inst.prop; // getter //123
EASYEXTENDING
class Foo {
    constructor(a,b) {
        this.x = a;
        this.y = b;
    }
    gimmeXY() {
        return this.x * this.y;
    }
}
class Bar extends Foo {
    constructor(a,b,c) {
        super( a, b );
        this.z = c;
    }
    gimmeXYZ() {
CLASSSUMMARY
Must be used with new operator, unlike ES5
Foo.call(obj);
It's not hoisted!
Can not declare properties outside of constructor
(except ES7 private proposal)
Can not access super properties in constructor
Constructor is optional
HANDLINGDI
class Ctrl{
    constructor(Service, AnotherService){
        this.Service = Service;
        this.AnotherService = AnotherService;
    }
    doSomething(){
        this.Service.doSomething();
    }
}
MYPREFERREDWAY
let internal;
class Ctrl{
    constructor(Service, AnotherService){
        internal = {Service, AnotherService};
    }
    doSomething(){
        internal.Service.doSomething();
    }
}
BECAREFULWITHGETTERS
<span ng­repeat="n in ctrl.items100 track by $index">
    {{e2Ctrl.test}}
</span>
class Ctrl{
    constructor(){
        this.items100 = new Array(100);
        this._test = 'some test value';
    }
    get test(){
        console.log('test');
        return this._test;
    }
}
//100x test + in digest cycles
COMMONLOGICINSERVICES
class StateAware{
    constructor(){
        this.state = {
            current: 'init'
        };
    }
    load(){
        this.state.current = 'loading';
        return this.loadData()
            .then((resp) => {
                this.data = resp;
            })
            .finally(() = > {
                this.state.current = 'ready';
            });
    }
}
HOWABOUTDIRECTIVES?
class Sample {
    constructor() {
        this.restrict = 'E';
        this.scope = {};
        this.controller = 'SampleCtrl';
        this.controllerAs = 'ctrl';
        this.templateUrl = 'sample.html';
        this.bindToController = {
            info: '='
        };
    }
}
angular.module('app').directive('sample', () => new Sample());
MODULES
KEEPINGITSIMPLE
console.log('This will fire on import');
var globalVariable = "This looks bad";
class Ctrl{
    something(){
        return 'something';
    }
}
angular.module('app').controller('Ctrl', Ctrl);
angular.module('app', []);
import 'Ctrl';
console.log(globalVariable);
//This will fire on import
//undefined
BEINGMORESPECIFIC
class Service{
    something(){
        return 'something';
    }
}
export default Service;
import Service from './services/Service';
angular.module('app', []).service('Service', Service);
BEINGPICKY
class Component{
    constructor(){
        //.. standard DDO
        this.controller = 'Ctrl';
        this.controllerAs = 'ctrl';
        this.bindToController = true;
        this.template = '<div>{{ctrl.something}}</div>';
    }
}
class Ctrl{
    constructor(){
        this.something = 'Some text';
    }
}
export { Component, Ctrl };
import {Component, Ctrl} from 'componentDirective';
angular.module('app', [])
    .controller('Ctrl', Ctrl)
    .directive('component', () => new Component());
IMPORTINGWITHALIAS
export function helperFunction(){ // ..}
export function getSomething(){ // ..}
export var randomVariable = 'o_O';
import * as lib from 'helpers';
lib.helperFunction();
console.log(lib.randomVariable);
WHYMODULES?
Standarized syntax
Better code organization
Avoid pollution of global namespace
let data = [
    {id: 1, name: 'John Snow', deleted: true},
    {id: 2, name: 'Ned Stark', deleted: true},
    //.. far far down ..
    {id: 60, name: 'Aria Stark', deleted: false}
];
Standard function
data.filter(function(person){
    return !person.deleted;
});
Arrow function
data.filter(person => !person.deleted);
USAGEINCALLBACKS
function Clickable(){
    this.clicks = 0;
    $('.elem').on('click', () => {
        this.clicks++;
        console.log(this.clicks);
    });
}
MULTIPLEARGUMENTCALLS
data.forEach((person, index) => {
    console.log(`${index}. ${person.name}`);
});
SYNTAXGOTCHA
let returnItem = id => ({id: id, name: 'Some name'});
SUMMARY
1. Lexical this
2. Can't change this
3. Can't be used with new
4. Don't have arguments array-like object
TEMPLATESTRINGS
let name = "Ice Cube";
let greeting = `Hello ${name}!`;
console.log(greeting); //Hello Ice Cube
var text =
`This is
more then one
line!`;
console.log( text );
//This is
//more then one
//line!
TAGGING
let message = Currency`You should pay ${value} @currency@ discount.`;
function Currency(templateData, ...args){
    return templateData.map((part, index) => {
        let str = part;
        if( args[index] ){
            str = part + String(args[index]);
        }
        return str.replace('@currency@', 'PLN');
    }).join('');
}
setOptions(0, 500); //500, 500, blur
DEFAULT,SPREAD,REST
ES5
function setOptions(debounce, interval, event){
    debounce = debounce || 500;
    interval = interval || 100;
    event = event || 'blur';
    console.info(debounce, interval, event);
}
setOptions(); //500, 100, blur
setOptions(200); //200, 100, blur
setOptions(undefined, null, 'change'); //500, 100, change
setOptions(undefined, null, 'change'); //500, 0, change
ES2015
function setOptions(debounce = 500, interval = 100, event = 'blur'){
    console.info(debounce, interval, event);
}
setOptions(); //500, 100, blur
setOptions(200); //200, 100, blur
setOptions(0, 500); //0, 500, blur
SPREAD
ES5
function foo(x,y,z) {
    console.log( x, y, z );
}
foo.apply( null, [1,2,3] );     // 1 2 3
ES2015
function foo(x,y,z) {
    console.log( x, y, z );
}
foo( ...[1,2,3] );              // 1 2 3
ANOTHERUSAGEOFSPREAD
let a = [2,3,4];
let b = [ 1, ...a, 5 ];
console.log( b );                   // [1,2,3,4,5]
REST
function foo(x, y, ...z) {
    console.log( x, y, z );
}
foo( 1, 2, 3, 4, 5 );           // 1 2 [3,4,5]
ES5
function test(){
    var args = Array.prototype.slice.call( arguments );
    //do sth
}
ES2015
function test(...args){
    //do sth
}
DESTRUCTURING,PROPERTYASSIGN
SHORTCUTS
ES5
function data(){
    return [1, 2, 3];
}
let tmp = data();
let a = tmp[0], //a = 1
    b = tmp[1], //b = 2
    c = tmp[2]; //c = 3
ES2015
function data(){
    return [1, 2, 3];
}
let [a,b,c] = data(); // a = 1, b = 2, c = 3
DESTRUCTURINGOBJECTS
function data(){
    return {
        firstName: 'John',
        lastName: 'Snow',
        occupation: 'Lord Commander of the Night's Watch'
    };
}
var {firstName, lastName: a, occupation: b} = data();
//firstName = 'John',
//a: 'Snow',
//b: 'Lord Commander of the Night's Watch'
UNIVERSITYCLASSIC-VARIABLESWAP
var x = 10, y = 20;
[ y, x ] = [ x, y ];
console.log( x, y );                // 20 10
DESTRUCTURENULLORUNDEFINED=
ERROR!
let {x, y} = null;
let {a, b} = undefined;
HOWEVERUNEXISTINGVARIABLES
AREOK
let options = {
    a: 1,
    b: 2
};
let {a, c} = options;
console.log(a); // 1
console.log(b); //undefined
console.log(c); //undefined
SYNTAXGOTCHA
let person = {
    id: 1,
    address: {
        street: 'Przy parku',
        city: 'Warszawa'
    }
};
let id;
let address;
{id, address} = person; //Error
({id, address} = person); //Ok!
OBJECTSANDARRAYSARE
DESTRUCTUREDASREFERENCES!
let color = {
    name: 'white',
    rgb: [255, 255, 255]
};
let {name: colorName, rgb} = color;
console.log(colorName); //'white'
console.log(rgb); //[255, 255, 255]
console.log(rgb === color.rgb); // true
DESTRUCTUREFUNCTIONPARAMS
ES5
function setCookie(name, value, options){
    options = options || {};
    let secure = options.secure;
    let path = options.path;
    let domain = options.domain;
    //....
}
setCookie('presentation', 'es2015', {
    secure: false;
});
DESTRUCTUREFUNCTIONPARAMS
ES2015
function setCookie(name, value, {secure, path, domain} = {}){
    //...
}
setCookie('presentation', 'es2015', {
    secure: false;
});
PROMISES
ES2015PROMISESYNTAX
var promise = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000);
});
REMOVINGCALLBACKLEGACYCODE
import LegacyLib from 'LegacyLib';
let internal;
class LegacyLibDecorator{
    constructor($q){
        internal = {$q};
    }
    loadData(){
        let deferred = $q.defer();
        LegacyLib.loadData(
            result => deferred.resolve(result),
            error => deferred.reject(error)
        );
        return deferred;
    }
}
REFACTORUSINGPROMISESYNTAX
import LegacyLib from 'LegacyLib';
let internal;
class LegacyLibDecorator{
    constructor($q){
        internal = {$q};
    }
    loadData(){
        return $q((resolve, reject) => {
            LegacyLib.loadData(
                result => resolve(result),
                error => reject(error)
            );
        });
    }
}
Mozilla Hacks: ES6 in depth
ExploringJS
Feature overview
Babel learn-es6
Great talk to go to next
http://hacks.mozilla.org/category/es6-in-depth
http://exploringjs.com/es6/
http://github.com/lukehoban/es6features
http://babeljs.io/docs/learn-es2015/
https://www.youtube.com/watch?v=DqMFX91ToLw

Contenu connexe

Similaire à ES2015 - enhance angular 1x applications

.NET 4 Demystified - Sandeep Joshi
.NET 4 Demystified - Sandeep Joshi.NET 4 Demystified - Sandeep Joshi
.NET 4 Demystified - Sandeep Joshi
Spiffy
 
Declarative authorization in REST services in SharePoint with F# and ServiceS...
Declarative authorization in REST services in SharePoint with F# and ServiceS...Declarative authorization in REST services in SharePoint with F# and ServiceS...
Declarative authorization in REST services in SharePoint with F# and ServiceS...
Sergey Tihon
 

Similaire à ES2015 - enhance angular 1x applications (20)

Deep Dive into Entity Framework 6.0
Deep Dive into Entity Framework 6.0Deep Dive into Entity Framework 6.0
Deep Dive into Entity Framework 6.0
 
ES6, A Look Into Your Future
ES6, A Look Into Your FutureES6, A Look Into Your Future
ES6, A Look Into Your Future
 
.Net language support
.Net language support.Net language support
.Net language support
 
A Tour of EF Core's (1.1) Most Interesting & Important Features
A Tour of EF Core's (1.1) Most Interesting & Important FeaturesA Tour of EF Core's (1.1) Most Interesting & Important Features
A Tour of EF Core's (1.1) Most Interesting & Important Features
 
Eclipse RCP Overview @ Rheinjug
Eclipse RCP Overview @ RheinjugEclipse RCP Overview @ Rheinjug
Eclipse RCP Overview @ Rheinjug
 
EF6 or EF Core? How Do I Choose?
EF6 or EF Core? How Do I Choose?EF6 or EF Core? How Do I Choose?
EF6 or EF Core? How Do I Choose?
 
Enterprise PL1 - Peter Elderon
Enterprise PL1 - Peter ElderonEnterprise PL1 - Peter Elderon
Enterprise PL1 - Peter Elderon
 
.NET Core, ASP.NET Core Course, Session 16
.NET Core, ASP.NET Core Course, Session 16.NET Core, ASP.NET Core Course, Session 16
.NET Core, ASP.NET Core Course, Session 16
 
The Nuxeo Way: leveraging open source to build a world-class ECM platform
The Nuxeo Way: leveraging open source to build a world-class ECM platformThe Nuxeo Way: leveraging open source to build a world-class ECM platform
The Nuxeo Way: leveraging open source to build a world-class ECM platform
 
Java 8 - New Updates and Why It Matters?
Java 8 - New Updates and Why It Matters?Java 8 - New Updates and Why It Matters?
Java 8 - New Updates and Why It Matters?
 
What’s New and Hot in .NET 4.0
What’s New and Hot in .NET 4.0What’s New and Hot in .NET 4.0
What’s New and Hot in .NET 4.0
 
.NET 4 Demystified - Sandeep Joshi
.NET 4 Demystified - Sandeep Joshi.NET 4 Demystified - Sandeep Joshi
.NET 4 Demystified - Sandeep Joshi
 
Eclipse 2011 Hot Topics
Eclipse 2011 Hot TopicsEclipse 2011 Hot Topics
Eclipse 2011 Hot Topics
 
Beginner's Guide to Angular 2.0
Beginner's Guide to Angular 2.0Beginner's Guide to Angular 2.0
Beginner's Guide to Angular 2.0
 
tutorials-visual-studio_visual-studio-2015-preview-comes-with-emulator-for-an...
tutorials-visual-studio_visual-studio-2015-preview-comes-with-emulator-for-an...tutorials-visual-studio_visual-studio-2015-preview-comes-with-emulator-for-an...
tutorials-visual-studio_visual-studio-2015-preview-comes-with-emulator-for-an...
 
Eclipse Democamp Nantes 2017 - Back to the Future: EclipseConverge & Devoxx US
Eclipse Democamp Nantes 2017 - Back to the Future: EclipseConverge & Devoxx USEclipse Democamp Nantes 2017 - Back to the Future: EclipseConverge & Devoxx US
Eclipse Democamp Nantes 2017 - Back to the Future: EclipseConverge & Devoxx US
 
Declarative authorization in REST services in SharePoint with F# and ServiceS...
Declarative authorization in REST services in SharePoint with F# and ServiceS...Declarative authorization in REST services in SharePoint with F# and ServiceS...
Declarative authorization in REST services in SharePoint with F# and ServiceS...
 
Viliam Elischer - Ember.js - Jak zatopit a neshořet!
Viliam Elischer - Ember.js - Jak zatopit a neshořet!Viliam Elischer - Ember.js - Jak zatopit a neshořet!
Viliam Elischer - Ember.js - Jak zatopit a neshořet!
 
Microsoft .NET 6 -What's All About The New Update
Microsoft .NET 6 -What's All About The New UpdateMicrosoft .NET 6 -What's All About The New Update
Microsoft .NET 6 -What's All About The New Update
 
Moving forward with ASP.NET Core
Moving forward with ASP.NET CoreMoving forward with ASP.NET Core
Moving forward with ASP.NET Core
 

Dernier

%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 

Dernier (20)

WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 

ES2015 - enhance angular 1x applications