Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ function gutenberg_register_scripts_and_styles() {
filemtime( gutenberg_dir_path() . 'build/core-data/index.js' ),
true
);
wp_register_script(
'wp-polyfill-dom-rect',
gutenberg_url( 'build/polyfills/dom-rect.js' ),
array(),
filemtime( gutenberg_dir_path() . 'build/polyfills/dom-rect.js' ),
true
);
wp_register_script(
'wp-dom',
gutenberg_url( 'build/dom/index.js' ),
Expand All @@ -220,7 +227,11 @@ function gutenberg_register_scripts_and_styles() {
wp_add_inline_script(
'wp-dom',
gutenberg_get_script_polyfill( array(
'document.contains' => 'wp-polyfill-node-contains',
'document.contains' => 'wp-polyfill-node-contains',
'"DOMRect" in this && ( function( DOMRect ) {' .
'try { new DOMRect(); return true; }' .
'catch ( e ) { return false; }' .
'}( this.DOMRect ) )' => 'wp-polyfill-dom-rect',
) ),
'before'
);
Expand Down
53 changes: 53 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"check-node-version": "3.1.1",
"codecov": "3.0.2",
"concurrently": "3.5.0",
"copy-webpack-plugin": "4.5.2",
"core-js": "2.5.7",
"cross-env": "3.2.4",
"deasync": "0.1.13",
Expand Down
7 changes: 7 additions & 0 deletions polyfills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Locally-maintained polyfills

We try to use third-party polyfills where possible but do not always find what we need. Even when we write our own, it's good to give back to the polyfill repositories we use like the [Financial Times' polyfill-service](https://github.com/Financial-Times/polyfill-service), but we do not control whether or when our polyfills will be merged and included with a new release. This is a place where we can maintain our own polyfills as needed.

## DOMRect

The DOMRect polyfill has been [submitted to the Financial Times' polyfill-service](https://github.com/Financial-Times/polyfill-service/pull/1732), but at of July 12, 2018, it has not been reviewed or merged. We need this polyfill, so we'll maintain a version here in the meantime.
110 changes: 110 additions & 0 deletions polyfills/dom-rect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
( function( global ) {
function number( v ) {
return v === undefined ? 0 : Number( v );
}

function different( u, v ) {
return u !== v && ! ( isNaN( u ) && isNaN( v ) );
}

function DOMRect( xArg, yArg, wArg, hArg ) {
let x, y, width, height, left, right, top, bottom;

x = number( xArg );
y = number( yArg );
width = number( wArg );
height = number( hArg );

Object.defineProperties( this, {
x: {
get: function() {
return x;
},
set: function( newX ) {
if ( different( x, newX ) ) {
x = newX;
left = right = undefined;
}
},
enumerable: true,
},
y: {
get: function() {
return y;
},
set: function( newY ) {
if ( different( y, newY ) ) {
y = newY;
top = bottom = undefined;
}
},
enumerable: true,
},
width: {
get: function() {
return width;
},
set: function( newWidth ) {
if ( different( width, newWidth ) ) {
width = newWidth;
left = right = undefined;
}
},
enumerable: true,
},
height: {
get: function() {
return height;
},
set: function( newHeight ) {
if ( different( height, newHeight ) ) {
height = newHeight;
top = bottom = undefined;
}
},
enumerable: true,
},
left: {
get: function() {
if ( left === undefined ) {
left = x + Math.min( 0, width );
}
return left;
},
enumerable: true,
},
right: {
get: function() {
if ( right === undefined ) {
right = x + Math.max( 0, width );
}
return right;
},
enumerable: true,
},
top: {
get: function() {
if ( top === undefined ) {
top = y + Math.min( 0, height );
}
return top;
},
enumerable: true,
},
bottom: {
get: function() {
if ( bottom === undefined ) {
bottom = y + Math.max( 0, height );
}
return bottom;
},
enumerable: true,
},
} );
}

global.DOMRect = DOMRect;
}(
// Support `module.exports` to facilitate unit test.
typeof module === 'undefined' ? this : module.exports
) );
175 changes: 175 additions & 0 deletions polyfills/test/dom-rect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Use `require` because the polyfill uses `module.exports` to provide itself for unit test.
const { DOMRect } = require( '../dom-rect' );

describe( 'DOMRect', function() {
describe( 'constructor', function() {
it( 'should create DOMRect with specified x, y, width, and height properties', function() {
const domRect = new DOMRect( 12, 34, 56, 78 );
expect( domRect.x ).toBe( 12 );
expect( domRect.y ).toBe( 34 );
expect( domRect.width ).toBe( 56 );
expect( domRect.height ).toBe( 78 );
} );
it( 'should default undefined arguments to zero', function() {
const domRect = new DOMRect();
expect( domRect.x ).toBe( 0 );
expect( domRect.y ).toBe( 0 );
expect( domRect.width ).toBe( 0 );
expect( domRect.height ).toBe( 0 );
} );
it( 'should interpret non-numeric arguments as NaN', function() {
let domRect = new DOMRect( 'text', 34, 56, 78 );
expect( isNaN( domRect.x ) ).toBeTruthy();
expect( domRect.y ).toBe( 34 );
expect( domRect.width ).toBe( 56 );
expect( domRect.height ).toBe( 78 );
domRect = new DOMRect( 12, 'text', 56, 78 );
expect( domRect.x ).toBe( 12 );
expect( isNaN( domRect.y ) ).toBeTruthy();
expect( domRect.width ).toBe( 56 );
expect( domRect.height ).toBe( 78 );
domRect = new DOMRect( 12, 34, 'text', 78 );
expect( domRect.x ).toBe( 12 );
expect( domRect.y ).toBe( 34 );
expect( isNaN( domRect.width ) ).toBeTruthy();
expect( domRect.height ).toBe( 78 );
domRect = new DOMRect( 12, 34, 56, 'text' );
expect( domRect.x ).toBe( 12 );
expect( domRect.y ).toBe( 34 );
expect( domRect.width ).toBe( 56 );
expect( isNaN( domRect.height ) ).toBeTruthy();
} );
} );

describe( 'writable properties', function() {
it( 'should define `x` as writable', function() {
const domRect = new DOMRect();
domRect.x = 321;
expect( domRect.x ).toBe( 321 );
} );

it( 'should define `y` as writable', function() {
const domRect = new DOMRect();
domRect.y = 321;
expect( domRect.y ).toBe( 321 );
} );

it( 'should define `width` as writable', function() {
const domRect = new DOMRect();
domRect.width = 321;
expect( domRect.width ).toBe( 321 );
} );

it( 'should define `height` as writable', function() {
const domRect = new DOMRect();
domRect.height = 321;
expect( domRect.height ).toBe( 321 );
} );
} );

describe( 'readonly properties', function() {
// Explicitly use strict mode so TypeErrors are thrown
// when assigning to readonly properties.
'use strict';

it( 'should define `left` as readonly', function() {
expect.hasAssertions();

const domRect = new DOMRect( 10, 20, 30, 40 );
try {
domRect.left = 321;
} catch ( e ) {
expect( e ).toBeInstanceOf( TypeError );
expect( domRect.left ).toBe( /* x */ 10 );
}
} );

it( 'should define `right` as readonly', function() {
expect.hasAssertions();

const domRect = new DOMRect( 10, 20, 30, 40 );
try {
domRect.right = 321;
} catch ( e ) {
expect( e ).toBeInstanceOf( TypeError );
expect( domRect.right ).toBe( /* x + width */ 40 );
}
} );

it( 'should define `top` as readonly', function() {
expect.hasAssertions();

const domRect = new DOMRect( 10, 20, 30, 40 );
try {
domRect.top = 321;
} catch ( e ) {
expect( e ).toBeInstanceOf( TypeError );
expect( domRect.top ).toBe( /* y */ 20 );
}
} );

it( 'should define `bottom` as readonly', function() {
expect.hasAssertions();

const domRect = new DOMRect( 10, 20, 30, 40 );
try {
domRect.bottom = 321;
} catch ( e ) {
expect( e ).toBeInstanceOf( TypeError );
expect( domRect.bottom ).toBe( /* y + height */ 60 );
}
} );

it( 'should have correct `left` and `right` when `width` is positive', function() {
const domRect = new DOMRect( 100, 0, 200, 0 );
expect( domRect.left ).toBe( /* x */ 100 );
expect( domRect.right ).toBe( /* x + width */ 300 );
} );

it( 'should have correct `left` and `right` when `width` is negative', function() {
const domRect = new DOMRect( 100, 0, -200, 0 );
expect( domRect.left ).toBe( /* x + width */ -100 );
expect( domRect.right ).toBe( /* x */ 100 );
} );

it( 'should have correct `top` and `bottom` when `height` is positive', function() {
const domRect = new DOMRect( 0, 100, 0, 200 );
expect( domRect.top ).toBe( /* y */ 100 );
expect( domRect.bottom ).toBe( /* y + height */ 300 );
} );

it( 'should have correct `top` and `bottom` when `height` is negative', function() {
const domRect = new DOMRect( 0, 100, 0, -200 );
expect( domRect.top ).toBe( /* y + height */ -100 );
expect( domRect.bottom ).toBe( /* y */ 100 );
} );

it( 'should have correct `left` and `right` when `x` is changed', function() {
const domRect = new DOMRect( 100, 0, 200, 0 );
domRect.x = 50;
expect( domRect.left ).toBe( /* x */ 50 );
expect( domRect.right ).toBe( /* x + width */ 250 );
} );

it( 'should have correct `left` and `right` when `width` is changed', function() {
const domRect = new DOMRect( 100, 0, 200, 0 );
domRect.width = 300;
expect( domRect.left ).toBe( /* x */ 100 );
expect( domRect.right ).toBe( /* x + width */ 400 );
} );

it( 'should have correct `top` and `bottom` when `y` is changed', function() {
const domRect = new DOMRect( 0, 100, 0, 200 );
domRect.y = 50;
expect( domRect.top ).toBe( /* y */ 50 );
expect( domRect.bottom ).toBe( /* y + height */ 250 );
} );

it( 'should have correct `top` and `bottom` when `height` is changed', function() {
const domRect = new DOMRect( 0, 100, 0, 200 );
domRect.height = 300;
expect( domRect.top ).toBe( /* y */ 100 );
expect( domRect.bottom ).toBe( /* y + height */ 400 );
} );
} );
} );
Loading